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

[1/9] incubator-tinkerpop git commit: Altered transaction management in Gremlin Server

Repository: incubator-tinkerpop
Updated Branches:
  refs/heads/master 039828bdc -> 6be9ce075


Altered transaction management in Gremlin Server

Removed the approach that did a commit prior to iteration and serialization as this opened a new transaction and wasn't optimal.  Instead, introduced a Frame abstraction that allowed serialization to occur during iteration of results.  In this way, results could be serialized in the same thread (and thus the same transaction) and errors in some graphs could be avoided.  The commit now occurs after the last item is serialized in the result set.  The last message is only flushed to the client after the commit occurs which assures that the the client shouldn't be able to send it's next request prior to that one being fully done.


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

Branch: refs/heads/master
Commit: dc48957cc06e6d5bd3b3ad500b47d117dcc3cc3a
Parents: 30e917f
Author: Stephen Mallette <sp...@genoprime.com>
Authored: Tue Dec 15 18:00:27 2015 -0500
Committer: Stephen Mallette <sp...@genoprime.com>
Committed: Tue Dec 15 18:00:27 2015 -0500

----------------------------------------------------------------------
 .../tinkerpop/gremlin/server/GraphManager.java  |  12 +--
 .../gremlin/server/channel/NioChannelizer.java  |  11 +-
 .../server/channel/WebSocketChannelizer.java    |  12 ++-
 .../tinkerpop/gremlin/server/handler/Frame.java |  37 +++++++
 .../handler/GremlinResponseFrameEncoder.java    | 102 +++++++++++++++++++
 .../handler/NioGremlinResponseFrameEncoder.java |  45 ++++++++
 .../handler/WsGremlinResponseEncoder.java       | 101 ------------------
 .../handler/WsGremlinResponseFrameEncoder.java  |  44 ++++++++
 .../server/op/AbstractEvalOpProcessor.java      |  99 +++++++++++++-----
 9 files changed, 324 insertions(+), 139 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/dc48957c/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/GraphManager.java
----------------------------------------------------------------------
diff --git a/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/GraphManager.java b/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/GraphManager.java
index d633cad..778e87a 100644
--- a/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/GraphManager.java
+++ b/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/GraphManager.java
@@ -99,9 +99,9 @@ public final class GraphManager {
      */
     public void rollbackAll() {
         graphs.entrySet().forEach(e -> {
-            final Graph g = e.getValue();
-            if (g.features().graph().supportsTransactions())
-                g.tx().rollback();
+            final Graph graph = e.getValue();
+            if (graph.features().graph().supportsTransactions())
+                graph.tx().rollback();
         });
     }
 
@@ -117,9 +117,9 @@ public final class GraphManager {
      */
     public void commitAll() {
         graphs.entrySet().forEach(e -> {
-            final Graph g = e.getValue();
-            if (g.features().graph().supportsTransactions())
-                g.tx().commit();
+            final Graph graph = e.getValue();
+            if (graph.features().graph().supportsTransactions())
+                graph.tx().commit();
         });
     }
 

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/dc48957c/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/channel/NioChannelizer.java
----------------------------------------------------------------------
diff --git a/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/channel/NioChannelizer.java b/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/channel/NioChannelizer.java
index ec0eeaf..d97cf83 100644
--- a/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/channel/NioChannelizer.java
+++ b/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/channel/NioChannelizer.java
@@ -21,12 +21,15 @@ package org.apache.tinkerpop.gremlin.server.channel;
 import io.netty.channel.EventLoopGroup;
 import org.apache.tinkerpop.gremlin.server.AbstractChannelizer;
 import org.apache.tinkerpop.gremlin.server.auth.AllowAllAuthenticator;
+import org.apache.tinkerpop.gremlin.server.handler.GremlinResponseFrameEncoder;
 import org.apache.tinkerpop.gremlin.server.handler.NioGremlinBinaryRequestDecoder;
 import org.apache.tinkerpop.gremlin.server.handler.NioGremlinResponseEncoder;
 import io.netty.channel.ChannelPipeline;
 import io.netty.handler.logging.LogLevel;
 import io.netty.handler.logging.LoggingHandler;
+import org.apache.tinkerpop.gremlin.server.handler.NioGremlinResponseFrameEncoder;
 import org.apache.tinkerpop.gremlin.server.handler.SaslAuthenticationHandler;
+import org.apache.tinkerpop.gremlin.server.handler.WsGremlinResponseFrameEncoder;
 import org.apache.tinkerpop.gremlin.server.util.ServerGremlinExecutor;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -41,6 +44,8 @@ public class NioChannelizer extends AbstractChannelizer {
     private static final Logger logger = LoggerFactory.getLogger(NioChannelizer.class);
 
     private SaslAuthenticationHandler authenticationHandler;
+    private GremlinResponseFrameEncoder gremlinResponseFrameEncoder;
+    private NioGremlinResponseFrameEncoder nioGremlinResponseFrameEncoder;
 
     @Override
     public void init(final ServerGremlinExecutor<EventLoopGroup> serverGremlinExecutor) {
@@ -50,6 +55,9 @@ public class NioChannelizer extends AbstractChannelizer {
         if (authenticator != null)
             authenticationHandler = authenticator.getClass() == AllowAllAuthenticator.class ?
                     null : new SaslAuthenticationHandler(authenticator);
+
+        gremlinResponseFrameEncoder = new GremlinResponseFrameEncoder();
+        nioGremlinResponseFrameEncoder = new NioGremlinResponseFrameEncoder();
     }
 
     @Override
@@ -57,7 +65,8 @@ public class NioChannelizer extends AbstractChannelizer {
         if (logger.isDebugEnabled())
             pipeline.addLast(new LoggingHandler("log-io", LogLevel.DEBUG));
 
-        pipeline.addLast("response-encoder", new NioGremlinResponseEncoder());
+        pipeline.addLast("nio-frame-encoder", nioGremlinResponseFrameEncoder);
+        pipeline.addLast("response-frame-encoder", gremlinResponseFrameEncoder);
         pipeline.addLast("request-binary-decoder", new NioGremlinBinaryRequestDecoder(serializers));
 
         if (logger.isDebugEnabled())

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/dc48957c/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/channel/WebSocketChannelizer.java
----------------------------------------------------------------------
diff --git a/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/channel/WebSocketChannelizer.java b/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/channel/WebSocketChannelizer.java
index 64e544c..2373819 100644
--- a/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/channel/WebSocketChannelizer.java
+++ b/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/channel/WebSocketChannelizer.java
@@ -24,7 +24,8 @@ import org.apache.tinkerpop.gremlin.server.auth.AllowAllAuthenticator;
 import org.apache.tinkerpop.gremlin.server.handler.SaslAuthenticationHandler;
 import org.apache.tinkerpop.gremlin.server.handler.WsGremlinBinaryRequestDecoder;
 import org.apache.tinkerpop.gremlin.server.handler.WsGremlinCloseRequestDecoder;
-import org.apache.tinkerpop.gremlin.server.handler.WsGremlinResponseEncoder;
+import org.apache.tinkerpop.gremlin.server.handler.GremlinResponseFrameEncoder;
+import org.apache.tinkerpop.gremlin.server.handler.WsGremlinResponseFrameEncoder;
 import org.apache.tinkerpop.gremlin.server.handler.WsGremlinTextRequestDecoder;
 import io.netty.channel.ChannelPipeline;
 import io.netty.handler.codec.http.HttpObjectAggregator;
@@ -46,9 +47,10 @@ import org.slf4j.LoggerFactory;
 public class WebSocketChannelizer extends AbstractChannelizer {
     private static final Logger logger = LoggerFactory.getLogger(WebSocketChannelizer.class);
 
-    private WsGremlinResponseEncoder wsGremlinResponseEncoder;
+    private GremlinResponseFrameEncoder gremlinResponseFrameEncoder;
     private WsGremlinTextRequestDecoder wsGremlinTextRequestDecoder;
     private WsGremlinBinaryRequestDecoder wsGremlinBinaryRequestDecoder;
+    private WsGremlinResponseFrameEncoder wsGremlinResponseFrameEncoder;
     private WsGremlinCloseRequestDecoder wsGremlinCloseRequestDecoder;
     private SaslAuthenticationHandler authenticationHandler;
 
@@ -56,10 +58,11 @@ public class WebSocketChannelizer extends AbstractChannelizer {
     public void init(final ServerGremlinExecutor<EventLoopGroup> serverGremlinExecutor) {
         super.init(serverGremlinExecutor);
 
-        wsGremlinResponseEncoder = new WsGremlinResponseEncoder();
+        gremlinResponseFrameEncoder = new GremlinResponseFrameEncoder();
         wsGremlinTextRequestDecoder = new WsGremlinTextRequestDecoder(serializers);
         wsGremlinBinaryRequestDecoder = new WsGremlinBinaryRequestDecoder(serializers);
         wsGremlinCloseRequestDecoder = new WsGremlinCloseRequestDecoder(serializers);
+        wsGremlinResponseFrameEncoder = new WsGremlinResponseFrameEncoder();
 
         // configure authentication - null means don't bother to add authentication to the pipeline
         if (authenticator != null)
@@ -94,7 +97,8 @@ public class WebSocketChannelizer extends AbstractChannelizer {
         if (logger.isDebugEnabled())
             pipeline.addLast(new LoggingHandler("log-aggregator-encoder", LogLevel.DEBUG));
 
-        pipeline.addLast("response-encoder", wsGremlinResponseEncoder);
+        pipeline.addLast("ws-frame-encoder", wsGremlinResponseFrameEncoder);
+        pipeline.addLast("response-frame-encoder", gremlinResponseFrameEncoder);
         pipeline.addLast("request-text-decoder", wsGremlinTextRequestDecoder);
         pipeline.addLast("request-binary-decoder", wsGremlinBinaryRequestDecoder);
         pipeline.addLast("request-close-decoder", wsGremlinCloseRequestDecoder);

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/dc48957c/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/handler/Frame.java
----------------------------------------------------------------------
diff --git a/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/handler/Frame.java b/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/handler/Frame.java
new file mode 100644
index 0000000..e6a616f
--- /dev/null
+++ b/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/handler/Frame.java
@@ -0,0 +1,37 @@
+/*
+ * 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.server.handler;
+
+/**
+ * A holder for a {@code String} or {@code ByteBuf} that represents a message to be written back to the requesting
+ * client.
+ *
+ * @author Stephen Mallette (http://stephen.genoprime.com)
+ */
+public class Frame {
+    private final Object msg;
+
+    public Frame(final Object msg) {
+        this.msg = msg;
+    }
+
+    public Object getMsg() {
+        return msg;
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/dc48957c/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/handler/GremlinResponseFrameEncoder.java
----------------------------------------------------------------------
diff --git a/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/handler/GremlinResponseFrameEncoder.java b/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/handler/GremlinResponseFrameEncoder.java
new file mode 100644
index 0000000..50c177b
--- /dev/null
+++ b/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/handler/GremlinResponseFrameEncoder.java
@@ -0,0 +1,102 @@
+/*
+ * 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.server.handler;
+
+import com.codahale.metrics.Meter;
+import org.apache.tinkerpop.gremlin.driver.MessageSerializer;
+import org.apache.tinkerpop.gremlin.driver.message.ResponseMessage;
+import org.apache.tinkerpop.gremlin.driver.message.ResponseStatusCode;
+import org.apache.tinkerpop.gremlin.driver.ser.MessageTextSerializer;
+import org.apache.tinkerpop.gremlin.server.GremlinServer;
+import org.apache.tinkerpop.gremlin.server.op.session.Session;
+import org.apache.tinkerpop.gremlin.server.util.MetricManager;
+import io.netty.channel.ChannelHandler;
+import io.netty.channel.ChannelHandlerContext;
+import io.netty.handler.codec.MessageToMessageEncoder;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.List;
+
+import static com.codahale.metrics.MetricRegistry.name;
+
+/**
+ * Ensures that any {@link ResponseMessage} manages to get converted to a {@link Frame}. By converting to {@link Frame}
+ * downstream protocols can treat the generic {@link Frame} any way it wants (e.g. write it back as a byte array,
+ * websocket frame, etc).
+ *
+ * @author Stephen Mallette (http://stephen.genoprime.com)
+ */
+@ChannelHandler.Sharable
+public class GremlinResponseFrameEncoder extends MessageToMessageEncoder<ResponseMessage> {
+    private static final Logger logger = LoggerFactory.getLogger(GremlinResponseFrameEncoder.class);
+    static final Meter errorMeter = MetricManager.INSTANCE.getMeter(name(GremlinServer.class, "errors"));
+
+    @Override
+    protected void encode(final ChannelHandlerContext ctx, final ResponseMessage o, final List<Object> objects) throws Exception {
+        final MessageSerializer serializer = ctx.channel().attr(StateKey.SERIALIZER).get();
+        final boolean useBinary = ctx.channel().attr(StateKey.USE_BINARY).get();
+        final Session session = ctx.channel().attr(StateKey.SESSION).get();
+
+        try {
+            if (!o.getStatus().getCode().isSuccess())
+                errorMeter.mark();
+
+            if (useBinary) {
+                final Frame serialized;
+
+                // if the request came in on a session then the serialization must occur in that same thread.
+                if (null == session)
+                    serialized = new Frame(serializer.serializeResponseAsBinary(o, ctx.alloc()));
+                else
+                    serialized = new Frame(session.getExecutor().submit(() -> serializer.serializeResponseAsBinary(o, ctx.alloc())).get());
+
+                objects.add(serialized);
+            } else {
+                // the expectation is that the GremlinTextRequestDecoder will have placed a MessageTextSerializer
+                // instance on the channel.
+                final MessageTextSerializer textSerializer = (MessageTextSerializer) serializer;
+
+                final Frame serialized;
+
+                // if the request came in on a session then the serialization must occur in that same thread.
+                if (null == session)
+                    serialized = new Frame(textSerializer.serializeResponseAsString(o));
+                else
+                    serialized = new Frame(session.getExecutor().submit(() -> textSerializer.serializeResponseAsString(o)).get());
+
+                objects.add(serialized);
+            }
+        } catch (Exception ex) {
+            errorMeter.mark();
+            logger.warn("The result [{}] in the request {} could not be serialized and returned.", o.getResult(), o.getRequestId(), ex);
+            final String errorMessage = String.format("Error during serialization: %s",
+                    ex.getCause() != null ? ex.getCause().getMessage() : ex.getMessage());
+            final ResponseMessage error = ResponseMessage.build(o.getRequestId())
+                    .statusMessage(errorMessage)
+                    .code(ResponseStatusCode.SERVER_ERROR_SERIALIZATION).create();
+            if (useBinary) {
+                objects.add(serializer.serializeResponseAsBinary(error, ctx.alloc()));
+            } else {
+                final MessageTextSerializer textSerializer = (MessageTextSerializer) serializer;
+                objects.add(textSerializer.serializeResponseAsString(error));
+            }
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/dc48957c/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/handler/NioGremlinResponseFrameEncoder.java
----------------------------------------------------------------------
diff --git a/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/handler/NioGremlinResponseFrameEncoder.java b/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/handler/NioGremlinResponseFrameEncoder.java
new file mode 100644
index 0000000..7c1c9d8
--- /dev/null
+++ b/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/handler/NioGremlinResponseFrameEncoder.java
@@ -0,0 +1,45 @@
+/*
+ * 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.server.handler;
+
+import io.netty.buffer.ByteBuf;
+import io.netty.channel.ChannelHandler;
+import io.netty.channel.ChannelHandlerContext;
+import io.netty.handler.codec.MessageToByteEncoder;
+import io.netty.util.CharsetUtil;
+
+/**
+ * @author Stephen Mallette (http://stephen.genoprime.com)
+ */
+@ChannelHandler.Sharable
+public class NioGremlinResponseFrameEncoder extends MessageToByteEncoder<Frame> {
+    @Override
+    protected void encode(final ChannelHandlerContext ctx, final Frame frame, final ByteBuf byteBuf) throws Exception {
+        if (frame.getMsg() instanceof ByteBuf) {
+            final ByteBuf bytes = (ByteBuf) frame.getMsg();
+            byteBuf.writeInt(bytes.capacity());
+            byteBuf.writeBytes(bytes);
+            bytes.release();
+        } else if (frame.getMsg() instanceof String) {
+            final byte [] bytes = ((String) frame.getMsg()).getBytes(CharsetUtil.UTF_8);
+            byteBuf.writeInt(bytes.length);
+            byteBuf.writeBytes(bytes);
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/dc48957c/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/handler/WsGremlinResponseEncoder.java
----------------------------------------------------------------------
diff --git a/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/handler/WsGremlinResponseEncoder.java b/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/handler/WsGremlinResponseEncoder.java
deleted file mode 100644
index 9855401..0000000
--- a/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/handler/WsGremlinResponseEncoder.java
+++ /dev/null
@@ -1,101 +0,0 @@
-/*
- * 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.server.handler;
-
-import com.codahale.metrics.Meter;
-import org.apache.tinkerpop.gremlin.driver.MessageSerializer;
-import org.apache.tinkerpop.gremlin.driver.message.ResponseMessage;
-import org.apache.tinkerpop.gremlin.driver.message.ResponseStatusCode;
-import org.apache.tinkerpop.gremlin.driver.ser.MessageTextSerializer;
-import org.apache.tinkerpop.gremlin.server.GremlinServer;
-import org.apache.tinkerpop.gremlin.server.op.session.Session;
-import org.apache.tinkerpop.gremlin.server.util.MetricManager;
-import io.netty.buffer.ByteBuf;
-import io.netty.channel.ChannelHandler;
-import io.netty.channel.ChannelHandlerContext;
-import io.netty.handler.codec.MessageToMessageEncoder;
-import io.netty.handler.codec.http.websocketx.BinaryWebSocketFrame;
-import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.util.List;
-
-import static com.codahale.metrics.MetricRegistry.name;
-
-/**
- * @author Stephen Mallette (http://stephen.genoprime.com)
- */
-@ChannelHandler.Sharable
-public class WsGremlinResponseEncoder extends MessageToMessageEncoder<ResponseMessage> {
-    private static final Logger logger = LoggerFactory.getLogger(WsGremlinResponseEncoder.class);
-    static final Meter errorMeter = MetricManager.INSTANCE.getMeter(name(GremlinServer.class, "errors"));
-
-    @Override
-    protected void encode(final ChannelHandlerContext ctx, final ResponseMessage o, final List<Object> objects) throws Exception {
-        final MessageSerializer serializer = ctx.channel().attr(StateKey.SERIALIZER).get();
-        final boolean useBinary = ctx.channel().attr(StateKey.USE_BINARY).get();
-        final Session session = ctx.channel().attr(StateKey.SESSION).get();
-
-        try {
-            if (!o.getStatus().getCode().isSuccess())
-                errorMeter.mark();
-
-            if (useBinary) {
-                final ByteBuf serialized;
-
-                // if the request came in on a session then the serialization must occur in that same thread.
-                if (null == session)
-                    serialized = serializer.serializeResponseAsBinary(o, ctx.alloc());
-                else
-                    serialized = session.getExecutor().submit(() -> serializer.serializeResponseAsBinary(o, ctx.alloc())).get();
-
-                objects.add(new BinaryWebSocketFrame(serialized));
-            } else {
-                // the expectation is that the GremlinTextRequestDecoder will have placed a MessageTextSerializer
-                // instance on the channel.
-                final MessageTextSerializer textSerializer = (MessageTextSerializer) serializer;
-
-                final String serialized;
-
-                // if the request came in on a session then the serialization must occur in that same thread.
-                if (null == session)
-                    serialized = textSerializer.serializeResponseAsString(o);
-                else
-                    serialized = session.getExecutor().submit(() -> textSerializer.serializeResponseAsString(o)).get();
-
-                objects.add(new TextWebSocketFrame(true, 0, serialized));
-            }
-        } catch (Exception ex) {
-            errorMeter.mark();
-            logger.warn("The result [{}] in the request {} could not be serialized and returned.", o.getResult(), o.getRequestId(), ex);
-            final String errorMessage = String.format("Error during serialization: %s",
-                    ex.getCause() != null ? ex.getCause().getMessage() : ex.getMessage());
-            final ResponseMessage error = ResponseMessage.build(o.getRequestId())
-                    .statusMessage(errorMessage)
-                    .code(ResponseStatusCode.SERVER_ERROR_SERIALIZATION).create();
-            if (useBinary) {
-                objects.add(new BinaryWebSocketFrame(serializer.serializeResponseAsBinary(error, ctx.alloc())));
-            } else {
-                final MessageTextSerializer textSerializer = (MessageTextSerializer) serializer;
-                objects.add(new TextWebSocketFrame(textSerializer.serializeResponseAsString(error)));
-            }
-        }
-    }
-}

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/dc48957c/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/handler/WsGremlinResponseFrameEncoder.java
----------------------------------------------------------------------
diff --git a/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/handler/WsGremlinResponseFrameEncoder.java b/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/handler/WsGremlinResponseFrameEncoder.java
new file mode 100644
index 0000000..ae9fc10
--- /dev/null
+++ b/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/handler/WsGremlinResponseFrameEncoder.java
@@ -0,0 +1,44 @@
+/*
+ * 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.server.handler;
+
+import io.netty.buffer.ByteBuf;
+import io.netty.channel.ChannelHandler;
+import io.netty.channel.ChannelHandlerContext;
+import io.netty.handler.codec.MessageToMessageEncoder;
+import io.netty.handler.codec.http.websocketx.BinaryWebSocketFrame;
+import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;
+
+import java.util.List;
+
+/**
+ * Encodes {@code ByteBuf} and {@code String} values to Websocket frames.
+ *
+ * @author Stephen Mallette (http://stephen.genoprime.com)
+ */
+@ChannelHandler.Sharable
+public class WsGremlinResponseFrameEncoder extends MessageToMessageEncoder<Frame> {
+    @Override
+    protected void encode(final ChannelHandlerContext ctx, final Frame o, final List<Object> objects) throws Exception {
+        if (o.getMsg() instanceof ByteBuf)
+            objects.add(new BinaryWebSocketFrame((ByteBuf) o.getMsg()));
+        else if (o.getMsg() instanceof String)
+            objects.add(new TextWebSocketFrame(true, 0, o.getMsg().toString()));
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/dc48957c/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/op/AbstractEvalOpProcessor.java
----------------------------------------------------------------------
diff --git a/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/op/AbstractEvalOpProcessor.java b/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/op/AbstractEvalOpProcessor.java
index f3dfae1..abaa8b5 100644
--- a/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/op/AbstractEvalOpProcessor.java
+++ b/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/op/AbstractEvalOpProcessor.java
@@ -20,14 +20,16 @@ package org.apache.tinkerpop.gremlin.server.op;
 
 import com.codahale.metrics.Meter;
 import com.codahale.metrics.Timer;
+import org.apache.tinkerpop.gremlin.driver.MessageSerializer;
 import org.apache.tinkerpop.gremlin.driver.Tokens;
 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.ser.MessageTextSerializer;
 import org.apache.tinkerpop.gremlin.groovy.engine.GremlinExecutor;
-import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversal;
-import org.apache.tinkerpop.gremlin.process.traversal.step.Mutating;
 import org.apache.tinkerpop.gremlin.server.GraphManager;
+import org.apache.tinkerpop.gremlin.server.handler.Frame;
+import org.apache.tinkerpop.gremlin.server.handler.StateKey;
 import org.apache.tinkerpop.gremlin.structure.T;
 import org.apache.tinkerpop.gremlin.server.Context;
 import org.apache.tinkerpop.gremlin.server.GremlinServer;
@@ -148,11 +150,12 @@ public abstract class AbstractEvalOpProcessor implements OpProcessor {
      *                         {@link GremlinExecutor#eval} method.
      */
     protected void evalOpInternal(final Context context, final Supplier<GremlinExecutor> gremlinExecutorSupplier,
-                              final BindingSupplier bindingsSupplier) throws OpProcessorException {
+                                  final BindingSupplier bindingsSupplier) throws OpProcessorException {
         final Timer.Context timerContext = evalOpTimer.time();
         final ChannelHandlerContext ctx = context.getChannelHandlerContext();
         final RequestMessage msg = context.getRequestMessage();
         final GremlinExecutor gremlinExecutor = gremlinExecutorSupplier.get();
+        final Settings settings = context.getSettings();
 
         final Map<String, Object> args = msg.getArgs();
 
@@ -171,9 +174,11 @@ public abstract class AbstractEvalOpProcessor implements OpProcessor {
                 final String errorMessage = String.format("Response iteration exceeded the configured threshold for request [%s] - %s", msg, ex.getMessage());
                 logger.warn(errorMessage);
                 ctx.writeAndFlush(ResponseMessage.build(msg).code(ResponseStatusCode.SERVER_ERROR_TIMEOUT).statusMessage(errorMessage).create());
+                if (manageTransactions) attemptRollback(msg, context.getGraphManager(), settings.strictTransactionManagement);
             } catch (Exception ex) {
                 logger.warn(String.format("Exception processing a script on request [%s].", msg), ex);
                 ctx.writeAndFlush(ResponseMessage.build(msg).code(ResponseStatusCode.SERVER_ERROR).statusMessage(ex.getMessage()).create());
+                if (manageTransactions) attemptRollback(msg, context.getGraphManager(), settings.strictTransactionManagement);
             }
         });
 
@@ -209,6 +214,8 @@ public abstract class AbstractEvalOpProcessor implements OpProcessor {
         final ChannelHandlerContext ctx = context.getChannelHandlerContext();
         final RequestMessage msg = context.getRequestMessage();
         final Settings settings = context.getSettings();
+        final MessageSerializer serializer = ctx.channel().attr(StateKey.SERIALIZER).get();
+        final boolean useBinary = ctx.channel().attr(StateKey.USE_BINARY).get();
         boolean warnOnce = false;
 
         // we have an empty iterator - happens on stuff like: g.V().iterate()
@@ -228,26 +235,6 @@ public abstract class AbstractEvalOpProcessor implements OpProcessor {
 
         // if we manage the transactions then we need to commit stuff now that eval is complete.
         Iterator toIterate = itty;
-        if (manageTransactions) {
-            // If the eval returned a Traversal then it gets special treatment
-            if (itty instanceof GraphTraversal) {
-                final GraphTraversal traversal = (GraphTraversal) itty;
-
-                // if it has Mutating steps then it needs to be iterated to produce the mutations in the transaction.
-                // after it is iterated then we can commit.  of course, this comes at the expense of being able
-                // to stream results back to the client as the result has to be realized into memory.
-                //
-                // labmdas are a loophole here.  for now, users will need to self iterate if they need lambdas :/
-                final boolean hasMutating = traversal.asAdmin().getSteps().stream().anyMatch(s -> s instanceof Mutating);
-                if (hasMutating) toIterate = IteratorUtils.list(itty).iterator();
-            }
-
-            // in any case, the commit should occur because at this point a GraphTraversal has been iterated OR
-            // the script has been executed. failures will bubble up before we start to iterate results which makes
-            // sense as we wouldn't want to waste time sending back results when the transaction is going to end up
-            // failing
-            attemptCommit(msg, context.getGraphManager(), settings.strictTransactionManagement);
-        }
 
         // the batch size can be overridden by the request
         final int resultIterationBatchSize = (Integer) msg.optionalArgs(Tokens.ARGS_BATCH_SIZE)
@@ -267,12 +254,27 @@ public abstract class AbstractEvalOpProcessor implements OpProcessor {
             if (ctx.channel().isWritable()) {
                 if (aggregate.size() == resultIterationBatchSize || !toIterate.hasNext()) {
                     final ResponseStatusCode code = toIterate.hasNext() ? ResponseStatusCode.PARTIAL_CONTENT : ResponseStatusCode.SUCCESS;
-                    ctx.writeAndFlush(ResponseMessage.build(msg)
-                                .code(code)
-                                .result(aggregate).create());
+
+                    // serialize here because in sessionless requests the serialization must occur in the same
+                    // thread as the eval.  as eval occurs in the GremlinExecutor there's no way to get back to the
+                    // thread that processed the eval of the script so, we have to push serialization down into that
+                    serializeResponseMessage(ctx, msg, serializer, useBinary, aggregate, code);
 
                     // only need to reset the aggregation list if there's more stuff to write
-                    if (toIterate.hasNext()) aggregate = new ArrayList<>(resultIterationBatchSize);
+                    if (toIterate.hasNext())
+                        aggregate = new ArrayList<>(resultIterationBatchSize);
+                    else {
+                        // iteration and serialization are both complete which means this finished successfully. note that
+                        // errors internal to script eval or timeout will rollback given GremlinServer's global configurations.
+                        // local errors will get rolledback below because the exceptions aren't thrown in those cases to be
+                        // caught by the GremlinExecutor for global rollback logic. this only needs to be committed if
+                        // there are no more items to iterate and serialization is complete
+                        if (manageTransactions && !toIterate.hasNext()) attemptCommit(msg, context.getGraphManager(), settings.strictTransactionManagement);
+                    }
+
+                    // the flush is called after the commit has potentially occurred.  in this way, if a commit was
+                    // required then it will be 100% complete before the client receives it.
+                    ctx.flush();
                 }
             } else {
                 // don't keep triggering this warning over and over again for the same request
@@ -299,6 +301,36 @@ public abstract class AbstractEvalOpProcessor implements OpProcessor {
         stopWatch.stop();
     }
 
+    private static void serializeResponseMessage(final ChannelHandlerContext ctx, final RequestMessage msg,
+                                                 final MessageSerializer serializer, final boolean useBinary, List<Object> aggregate,
+                                                 final ResponseStatusCode code) {
+        try {
+            if (useBinary) {
+                ctx.write(new Frame(
+                        serializer.serializeResponseAsBinary(ResponseMessage.build(msg)
+                        .code(code)
+                        .result(aggregate).create(), ctx.alloc())));
+            } else {
+                // the expectation is that the GremlinTextRequestDecoder will have placed a MessageTextSerializer
+                // instance on the channel.
+                final MessageTextSerializer textSerializer = (MessageTextSerializer) serializer;
+                ctx.write(new Frame(
+                        textSerializer.serializeResponseAsString(ResponseMessage.build(msg)
+                        .code(code)
+                        .result(aggregate).create())));
+            }
+        } catch (Exception ex) {
+            errorMeter.mark();
+            logger.warn("The result [{}] in the request {} could not be serialized and returned.", aggregate, msg.getRequestId(), ex);
+            final String errorMessage = String.format("Error during serialization: %s",
+                    ex.getCause() != null ? ex.getCause().getMessage() : ex.getMessage());
+            final ResponseMessage error = ResponseMessage.build(msg.getRequestId())
+                    .statusMessage(errorMessage)
+                    .code(ResponseStatusCode.SERVER_ERROR_SERIALIZATION).create();
+            ctx.writeAndFlush(error);
+        }
+    }
+
     private static void attemptCommit(final RequestMessage msg, final GraphManager graphManager, final boolean strict) {
         if (strict) {
             // assumes that validations will already have been performed in extending classes - they are performed
@@ -312,6 +344,19 @@ public abstract class AbstractEvalOpProcessor implements OpProcessor {
         }
     }
 
+    private static void attemptRollback(final RequestMessage msg, final GraphManager graphManager, final boolean strict) {
+        if (strict) {
+            // assumes that validations will already have been performed in extending classes - they are performed
+            // in StandardOpProcessor when getting bindings right now
+            final boolean hasRebindings = msg.getArgs().containsKey(Tokens.ARGS_REBINDINGS);
+            final String rebindingOrAliasParameter = hasRebindings ? Tokens.ARGS_REBINDINGS : Tokens.ARGS_ALIASES;
+            final Map<String, String> aliases = (Map<String, String>) msg.getArgs().get(rebindingOrAliasParameter);
+            graphManager.rollback(new HashSet<>(aliases.values()));
+        } else {
+            graphManager.rollbackAll();
+        }
+    }
+
     @FunctionalInterface
     public interface BindingSupplier {
         public Bindings get() throws OpProcessorException;



[4/9] incubator-tinkerpop git commit: Check for open transactions before doing an auto commit/rollback.

Posted by sp...@apache.org.
Check for open transactions before doing an auto commit/rollback.

By adding this check Gremlin Server only commits/rollsback at the start of a request or at the error driven end of a request. This should prevent graphs from creating extra transactions when they are not needed (which might be expensive to do for some graphs).


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

Branch: refs/heads/master
Commit: f34bde7a98b98f013f9bface26fe449197aece0d
Parents: 0b9556d
Author: Stephen Mallette <sp...@genoprime.com>
Authored: Wed Dec 16 11:29:09 2015 -0500
Committer: Stephen Mallette <sp...@genoprime.com>
Committed: Wed Dec 16 11:29:09 2015 -0500

----------------------------------------------------------------------
 .../java/org/apache/tinkerpop/gremlin/server/GraphManager.java | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/f34bde7a/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/GraphManager.java
----------------------------------------------------------------------
diff --git a/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/GraphManager.java b/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/GraphManager.java
index 778e87a..b28493e 100644
--- a/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/GraphManager.java
+++ b/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/GraphManager.java
@@ -100,7 +100,7 @@ public final class GraphManager {
     public void rollbackAll() {
         graphs.entrySet().forEach(e -> {
             final Graph graph = e.getValue();
-            if (graph.features().graph().supportsTransactions())
+            if (graph.features().graph().supportsTransactions() && graph.tx().isOpen())
                 graph.tx().rollback();
         });
     }
@@ -118,7 +118,7 @@ public final class GraphManager {
     public void commitAll() {
         graphs.entrySet().forEach(e -> {
             final Graph graph = e.getValue();
-            if (graph.features().graph().supportsTransactions())
+            if (graph.features().graph().supportsTransactions() && graph.tx().isOpen())
                 graph.tx().commit();
         });
     }
@@ -148,7 +148,7 @@ public final class GraphManager {
         });
 
         graphsToCloseTxOn.forEach(graph -> {
-            if (graph.features().graph().supportsTransactions()) {
+            if (graph.features().graph().supportsTransactions() && graph.tx().isOpen()) {
                 if (tx == Transaction.Status.COMMIT)
                     graph.tx().commit();
                 else


[8/9] incubator-tinkerpop git commit: Merge remote-tracking branch 'origin/TINKERPOP-1035'

Posted by sp...@apache.org.
Merge remote-tracking branch 'origin/TINKERPOP-1035'


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

Branch: refs/heads/master
Commit: 15bfb9f9880a267fef0c620b533bc86cca7927a2
Parents: b02b9f8 58cd806
Author: Stephen Mallette <sp...@genoprime.com>
Authored: Tue Jan 12 09:49:43 2016 -0500
Committer: Stephen Mallette <sp...@genoprime.com>
Committed: Tue Jan 12 09:49:43 2016 -0500

----------------------------------------------------------------------
 .../src/reference/gremlin-applications.asciidoc |  26 +---
 .../upgrade/release-3.1.x-incubating.asciidoc   |  14 +--
 .../tinkerpop/gremlin/server/GraphManager.java  |  14 +--
 .../gremlin/server/channel/NioChannelizer.java  |  11 +-
 .../server/channel/WebSocketChannelizer.java    |  12 +-
 .../tinkerpop/gremlin/server/handler/Frame.java |  37 ++++++
 .../handler/GremlinResponseFrameEncoder.java    | 102 ++++++++++++++++
 .../gremlin/server/handler/IteratorHandler.java |   2 +
 .../handler/NioGremlinResponseEncoder.java      |   4 +
 .../handler/NioGremlinResponseFrameEncoder.java |  47 +++++++
 .../server/handler/OpSelectorHandler.java       |  10 +-
 .../handler/WsGremlinResponseEncoder.java       |   6 +-
 .../handler/WsGremlinResponseFrameEncoder.java  |  44 +++++++
 .../server/op/AbstractEvalOpProcessor.java      | 121 ++++++++++++++-----
 14 files changed, 370 insertions(+), 80 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/15bfb9f9/docs/src/reference/gremlin-applications.asciidoc
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/15bfb9f9/docs/src/upgrade/release-3.1.x-incubating.asciidoc
----------------------------------------------------------------------


[9/9] incubator-tinkerpop git commit: Merge remote-tracking branch 'origin/master'

Posted by sp...@apache.org.
Merge remote-tracking branch 'origin/master'


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

Branch: refs/heads/master
Commit: 6be9ce07572c28f40906e772b4c384bc7cd4055d
Parents: 15bfb9f 039828b
Author: Stephen Mallette <sp...@genoprime.com>
Authored: Tue Jan 12 10:14:24 2016 -0500
Committer: Stephen Mallette <sp...@genoprime.com>
Committed: Tue Jan 12 10:14:24 2016 -0500

----------------------------------------------------------------------
 CHANGELOG.asciidoc                              |  1 +
 docs/src/reference/implementations.asciidoc     |  2 +
 .../lambda/AbstractLambdaTraversal.java         |  2 +-
 hadoop-gremlin/conf/hadoop-gryo.properties      |  2 +
 .../tinkerpop/gremlin/hadoop/Constants.java     |  2 +
 .../hadoop/structure/HadoopConfiguration.java   | 10 ++---
 .../process/computer/SparkGraphComputer.java    |  4 +-
 .../gremlin/spark/structure/Spark.java          |  3 +-
 .../spark/structure/io/PersistedOutputRDD.java  | 10 +++--
 .../io/PersistedInputOutputRDDTest.java         | 40 ++++++++++++++++++++
 10 files changed, 65 insertions(+), 11 deletions(-)
----------------------------------------------------------------------



[7/9] incubator-tinkerpop git commit: Used a independent loop control for result interation.

Posted by sp...@apache.org.
Used a independent loop control for result interation.

This solves a problem where a graph could automatically open a new transaction on the same request.  In the result iteration loop, a commit gets called if there are no results left, when the loop traverse back to the top of the while() to exit, it does a final check to Traversal.hasNext().  On some graphs, automatic transaction handling could open a new transaction there. subtle - oh so subtle.


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

Branch: refs/heads/master
Commit: 58cd80672c036f5b4eeab54e007627ca12c47800
Parents: 0e27005
Author: Stephen Mallette <sp...@genoprime.com>
Authored: Sat Jan 9 12:23:20 2016 -0500
Committer: Stephen Mallette <sp...@genoprime.com>
Committed: Sat Jan 9 12:23:20 2016 -0500

----------------------------------------------------------------------
 .../gremlin/server/op/AbstractEvalOpProcessor.java   | 15 +++++++++++++--
 1 file changed, 13 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/58cd8067/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/op/AbstractEvalOpProcessor.java
----------------------------------------------------------------------
diff --git a/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/op/AbstractEvalOpProcessor.java b/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/op/AbstractEvalOpProcessor.java
index 171edfb..4d85822 100644
--- a/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/op/AbstractEvalOpProcessor.java
+++ b/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/op/AbstractEvalOpProcessor.java
@@ -262,7 +262,13 @@ public abstract class AbstractEvalOpProcessor implements OpProcessor {
         final int resultIterationBatchSize = (Integer) msg.optionalArgs(Tokens.ARGS_BATCH_SIZE)
                 .orElse(settings.resultIterationBatchSize);
         List<Object> aggregate = new ArrayList<>(resultIterationBatchSize);
-        while (toIterate.hasNext()) {
+
+        // use an external control to manage the loop as opposed to just checking hasNext() in the while.  this
+        // prevent situations where auto transactions create a new transaction after calls to commit() withing
+        // the loop on calls to hasNext().
+        boolean hasMore = toIterate.hasNext();
+
+        while (hasMore) {
             if (Thread.interrupted()) throw new InterruptedException();
 
             // have to check the aggregate size because it is possible that the channel is not writeable (below)
@@ -291,7 +297,12 @@ public abstract class AbstractEvalOpProcessor implements OpProcessor {
                         // local errors will get rolledback below because the exceptions aren't thrown in those cases to be
                         // caught by the GremlinExecutor for global rollback logic. this only needs to be committed if
                         // there are no more items to iterate and serialization is complete
-                        if (manageTransactions && !toIterate.hasNext()) attemptCommit(msg, context.getGraphManager(), settings.strictTransactionManagement);
+                        if (manageTransactions) attemptCommit(msg, context.getGraphManager(), settings.strictTransactionManagement);
+
+                        // exit the result iteration loop as there are no more results left.  using this external control
+                        // because of the above commit.  some graphs may open a new transaction on the call to
+                        // hasNext()
+                        hasMore = false;
                     }
 
                     // the flush is called after the commit has potentially occurred.  in this way, if a commit was


[3/9] incubator-tinkerpop git commit: Deprecated some old handlers in Gremlin Server.

Posted by sp...@apache.org.
Deprecated some old handlers in Gremlin Server.

No one should be using these directly but as they are public, it felt better to just deprecate for now.


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

Branch: refs/heads/master
Commit: 0b9556d8e3e2b025103564ba2e57dc128583f18e
Parents: f81d5c4
Author: Stephen Mallette <sp...@genoprime.com>
Authored: Wed Dec 16 10:18:54 2015 -0500
Committer: Stephen Mallette <sp...@genoprime.com>
Committed: Wed Dec 16 10:18:54 2015 -0500

----------------------------------------------------------------------
 .../gremlin/server/channel/NioChannelizer.java  |   2 -
 .../gremlin/server/handler/IteratorHandler.java |   2 +
 .../handler/NioGremlinResponseEncoder.java      |   4 +
 .../handler/NioGremlinResponseFrameEncoder.java |   2 +
 .../handler/WsGremlinResponseEncoder.java       | 105 +++++++++++++++++++
 5 files changed, 113 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/0b9556d8/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/channel/NioChannelizer.java
----------------------------------------------------------------------
diff --git a/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/channel/NioChannelizer.java b/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/channel/NioChannelizer.java
index d97cf83..d2ba520 100644
--- a/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/channel/NioChannelizer.java
+++ b/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/channel/NioChannelizer.java
@@ -23,13 +23,11 @@ import org.apache.tinkerpop.gremlin.server.AbstractChannelizer;
 import org.apache.tinkerpop.gremlin.server.auth.AllowAllAuthenticator;
 import org.apache.tinkerpop.gremlin.server.handler.GremlinResponseFrameEncoder;
 import org.apache.tinkerpop.gremlin.server.handler.NioGremlinBinaryRequestDecoder;
-import org.apache.tinkerpop.gremlin.server.handler.NioGremlinResponseEncoder;
 import io.netty.channel.ChannelPipeline;
 import io.netty.handler.logging.LogLevel;
 import io.netty.handler.logging.LoggingHandler;
 import org.apache.tinkerpop.gremlin.server.handler.NioGremlinResponseFrameEncoder;
 import org.apache.tinkerpop.gremlin.server.handler.SaslAuthenticationHandler;
-import org.apache.tinkerpop.gremlin.server.handler.WsGremlinResponseFrameEncoder;
 import org.apache.tinkerpop.gremlin.server.util.ServerGremlinExecutor;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/0b9556d8/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/handler/IteratorHandler.java
----------------------------------------------------------------------
diff --git a/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/handler/IteratorHandler.java b/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/handler/IteratorHandler.java
index 2fcfc1b..527aa37 100644
--- a/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/handler/IteratorHandler.java
+++ b/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/handler/IteratorHandler.java
@@ -47,7 +47,9 @@ import java.util.concurrent.TimeoutException;
  * are passed to it, they do not contain large result sets or iterates over objects that require network calls.
  *
  * @author Stephen Mallette (http://stephen.genoprime.com)
+ * @deprecated As of release 3.1.1-incubating, not directly replaced.
  */
+@Deprecated
 @ChannelHandler.Sharable
 public class IteratorHandler extends ChannelOutboundHandlerAdapter {
     private static final Logger logger = LoggerFactory.getLogger(IteratorHandler.class);

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/0b9556d8/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/handler/NioGremlinResponseEncoder.java
----------------------------------------------------------------------
diff --git a/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/handler/NioGremlinResponseEncoder.java b/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/handler/NioGremlinResponseEncoder.java
index e62703f..6a98b8b 100644
--- a/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/handler/NioGremlinResponseEncoder.java
+++ b/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/handler/NioGremlinResponseEncoder.java
@@ -37,7 +37,11 @@ import static com.codahale.metrics.MetricRegistry.name;
 
 /**
  * @author Stephen Mallette (http://stephen.genoprime.com)
+ * @deprecated As of release 3.1.1-incubating, replaced by {@link NioGremlinResponseFrameEncoder} and
+ * {@link GremlinResponseFrameEncoder}
+ * @see <a href="https://issues.apache.org/jira/browse/TINKERPOP-1035">TINKERPOP-1035</a>
  */
+@Deprecated
 @ChannelHandler.Sharable
 public class NioGremlinResponseEncoder extends MessageToByteEncoder<ResponseMessage> {
     private static final Logger logger = LoggerFactory.getLogger(NioGremlinResponseEncoder.class);

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/0b9556d8/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/handler/NioGremlinResponseFrameEncoder.java
----------------------------------------------------------------------
diff --git a/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/handler/NioGremlinResponseFrameEncoder.java b/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/handler/NioGremlinResponseFrameEncoder.java
index 7c1c9d8..119b3ef 100644
--- a/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/handler/NioGremlinResponseFrameEncoder.java
+++ b/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/handler/NioGremlinResponseFrameEncoder.java
@@ -25,6 +25,8 @@ import io.netty.handler.codec.MessageToByteEncoder;
 import io.netty.util.CharsetUtil;
 
 /**
+ * Encodes {@code ByteBuf} and {@code String} values to bytes to be written over NIO.
+ *
  * @author Stephen Mallette (http://stephen.genoprime.com)
  */
 @ChannelHandler.Sharable

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/0b9556d8/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/handler/WsGremlinResponseEncoder.java
----------------------------------------------------------------------
diff --git a/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/handler/WsGremlinResponseEncoder.java b/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/handler/WsGremlinResponseEncoder.java
new file mode 100644
index 0000000..80565f1
--- /dev/null
+++ b/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/handler/WsGremlinResponseEncoder.java
@@ -0,0 +1,105 @@
+/*
+ * 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.server.handler;
+
+import com.codahale.metrics.Meter;
+import org.apache.tinkerpop.gremlin.driver.MessageSerializer;
+import org.apache.tinkerpop.gremlin.driver.message.ResponseMessage;
+import org.apache.tinkerpop.gremlin.driver.message.ResponseStatusCode;
+import org.apache.tinkerpop.gremlin.driver.ser.MessageTextSerializer;
+import org.apache.tinkerpop.gremlin.server.GremlinServer;
+import org.apache.tinkerpop.gremlin.server.op.session.Session;
+import org.apache.tinkerpop.gremlin.server.util.MetricManager;
+import io.netty.buffer.ByteBuf;
+import io.netty.channel.ChannelHandler;
+import io.netty.channel.ChannelHandlerContext;
+import io.netty.handler.codec.MessageToMessageEncoder;
+import io.netty.handler.codec.http.websocketx.BinaryWebSocketFrame;
+import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.List;
+
+import static com.codahale.metrics.MetricRegistry.name;
+
+/**
+ * @author Stephen Mallette (http://stephen.genoprime.com)
+ * @deprecated As of release 3.1.1-incubating, replaced by {@link WsGremlinResponseFrameEncoder} and
+ * {@link GremlinResponseFrameEncoder}
+ * @see <a href="https://issues.apache.org/jira/browse/TINKERPOP-1035">TINKERPOP-1035</a>
+ */
+@Deprecated
+@ChannelHandler.Sharable
+public class WsGremlinResponseEncoder extends MessageToMessageEncoder<ResponseMessage> {
+    private static final Logger logger = LoggerFactory.getLogger(WsGremlinResponseEncoder.class);
+    static final Meter errorMeter = MetricManager.INSTANCE.getMeter(name(GremlinServer.class, "errors"));
+
+    @Override
+    protected void encode(final ChannelHandlerContext ctx, final ResponseMessage o, final List<Object> objects) throws Exception {
+        final MessageSerializer serializer = ctx.channel().attr(StateKey.SERIALIZER).get();
+        final boolean useBinary = ctx.channel().attr(StateKey.USE_BINARY).get();
+        final Session session = ctx.channel().attr(StateKey.SESSION).get();
+
+        try {
+            if (!o.getStatus().getCode().isSuccess())
+                errorMeter.mark();
+
+            if (useBinary) {
+                final ByteBuf serialized;
+
+                // if the request came in on a session then the serialization must occur in that same thread.
+                if (null == session)
+                    serialized = serializer.serializeResponseAsBinary(o, ctx.alloc());
+                else
+                    serialized = session.getExecutor().submit(() -> serializer.serializeResponseAsBinary(o, ctx.alloc())).get();
+
+                objects.add(new BinaryWebSocketFrame(serialized));
+            } else {
+                // the expectation is that the GremlinTextRequestDecoder will have placed a MessageTextSerializer
+                // instance on the channel.
+                final MessageTextSerializer textSerializer = (MessageTextSerializer) serializer;
+
+                final String serialized;
+
+                // if the request came in on a session then the serialization must occur in that same thread.
+                if (null == session)
+                    serialized = textSerializer.serializeResponseAsString(o);
+                else
+                    serialized = session.getExecutor().submit(() -> textSerializer.serializeResponseAsString(o)).get();
+
+                objects.add(new TextWebSocketFrame(true, 0, serialized));
+            }
+        } catch (Exception ex) {
+            errorMeter.mark();
+            logger.warn("The result [{}] in the request {} could not be serialized and returned.", o.getResult(), o.getRequestId(), ex);
+            final String errorMessage = String.format("Error during serialization: %s",
+                    ex.getCause() != null ? ex.getCause().getMessage() : ex.getMessage());
+            final ResponseMessage error = ResponseMessage.build(o.getRequestId())
+                    .statusMessage(errorMessage)
+                    .code(ResponseStatusCode.SERVER_ERROR_SERIALIZATION).create();
+            if (useBinary) {
+                objects.add(new BinaryWebSocketFrame(serializer.serializeResponseAsBinary(error, ctx.alloc())));
+            } else {
+                final MessageTextSerializer textSerializer = (MessageTextSerializer) serializer;
+                objects.add(new TextWebSocketFrame(textSerializer.serializeResponseAsString(error)));
+            }
+        }
+    }
+}
\ No newline at end of file


[2/9] incubator-tinkerpop git commit: Updated documentation around transaction management.

Posted by sp...@apache.org.
Updated documentation around transaction management.


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

Branch: refs/heads/master
Commit: f81d5c4c194c7c25bb2125cc0ed1179f80ad5dd5
Parents: dc48957
Author: Stephen Mallette <sp...@genoprime.com>
Authored: Wed Dec 16 06:01:42 2015 -0500
Committer: Stephen Mallette <sp...@genoprime.com>
Committed: Wed Dec 16 06:01:42 2015 -0500

----------------------------------------------------------------------
 .../src/reference/gremlin-applications.asciidoc | 26 ++------------------
 .../upgrade/release-3.1.x-incubating.asciidoc   | 14 +----------
 2 files changed, 3 insertions(+), 37 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/f81d5c4c/docs/src/reference/gremlin-applications.asciidoc
----------------------------------------------------------------------
diff --git a/docs/src/reference/gremlin-applications.asciidoc b/docs/src/reference/gremlin-applications.asciidoc
index 96e25d7..7c1f83a 100644
--- a/docs/src/reference/gremlin-applications.asciidoc
+++ b/docs/src/reference/gremlin-applications.asciidoc
@@ -1193,25 +1193,8 @@ necessary for a given use case.
 Considering Transactions
 ^^^^^^^^^^^^^^^^^^^^^^^^
 
-Gremlin Server does automated transaction handling for "sessionless" requests (i.e. no state between requests). It
-will automatically commit or rollback transactions depending on the success or failure of the script. When submitting
-requests it is important to recognize that transaction management procedures may differ slightly depending on what is
-returned from the script.
-
-* If the script returns anything other than a `GraphTraversal`, a commit will be called just before results are
-iterated back to the client.
-* If the result is a `GraphTraversal` that has no `Mutating` steps, a commit will be called just before results are
-iterated back to the client.
-* If the result is a `GraphTraversal` that has one or more `Mutating` steps (i.e. one that modifies the `Graph`),
-the `GraphTraversal` will be iterated, it's results pushed to a `List`, commit called, and the result in the `List`
-iterated back to the client.
-
-The last bullet point above begs additional explanation.  Assume that the script `g.addV('name','stephen')` was
-submitted to the server.  That script returns a `GraphTraversal` and has a `Mutating` step. The traversal needs to
-be iterated in order for the mutations to take place or else the commit will have no effect. That's why Gremlin
-Server attempts to detect these types of traversals and treat them specially. The unfortunate downside is that the
-result of this script must be realized in memory which means that they aren't being streamed back to the client.
-For small results this likely should not present an issue.
+Gremlin Server performs automated transaction handling for "sessionless" requests (i.e. no state between requests). It
+will automatically commit or rollback transactions depending on the success or failure of the request.
 
 Another aspect of Transaction Management that should be considered is the usage of the `strictTransactionManagement`
 setting.  It is `false` by default, but when set to `true`, it forces the user to pass `aliases` for all requests.
@@ -1220,11 +1203,6 @@ Gremlin Server in this configuration should be more efficient when there are mul
 Gremlin Server will only close transactions on the graphs specified by the `aliases`. Keeping this setting `false`,
 will simply have Gremlin Server close transactions on all graphs for every request.
 
-NOTE: It is possible to bypass the transaction management system around `GraphTraversal` by using a lambda. Gremlin
-Server is only looking for `Mutating` steps, so a script like: `g.V().sideEffect{it.get().property('color','green')}`
-would not be iterated prior to commit and the mutations not realized.  If lambdas must be used then it is important
-to self-iterate by doing something like: `g.V().sideEffect{it.get().property('color','green')}.toList()`.
-
 Developing a Driver
 ~~~~~~~~~~~~~~~~~~~
 

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/f81d5c4c/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 b50f3e1..c93495e 100644
--- a/docs/src/upgrade/release-3.1.x-incubating.asciidoc
+++ b/docs/src/upgrade/release-3.1.x-incubating.asciidoc
@@ -35,18 +35,7 @@ Upgrading for Users
 Gremlin Server Transaction Management
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-There were some changes to how Gremlin Server manages transactions on sessionless requests to make the process more
-consistent across different graph databases. Commits now occur after evaluation and prior to result iteration, which
-ensures an earlier failure (i.e. prior to results getting to the client indicating a false success) and better
-handling of a result that is a `GraphTraversal` that mutates the `Graph`.
-
-This change likely does not require any changes to the code of users, but does introduce some items to be aware of
-when issuing scripts. Most specifically, using lambdas in a request that returns a `GraphTraversal`, designed to modify
-the `Graph`, will fail to do so unless it is self-iterated.  In other words, instead of sending:
-`g.V().sideEffect{it.get().property('color','green')}` one would send:
-`g.V().sideEffect{it.get().property('color','green')}.toList()`
-
-In addition, Gremlin Server now has a new setting called `strictTransactionManagement`, which forces the user to pass
+Gremlin Server now has a setting called `strictTransactionManagement`, which forces the user to pass
 `aliases` for all requests. The aliases are then used to determine which graphs will have their transactions closed
 for that request. The alternative is to continue with default operations where the transactions of all configured
 graphs will be closed. It is likely that `strictTransactionManagement` (which is `false` by default so as to be
@@ -54,7 +43,6 @@ backward compatible with previous versions) will become the future standard mode
 it provides a more efficient method for transaction management.
 
 See: link:https://issues.apache.org/jira/browse/TINKERPOP-930[TINKERPOP-930],
-link:https://issues.apache.org/jira/browse/TINKERPOP-1035[TINKERPOP-1035],
 link:http://tinkerpop.apache.org/docs/3.1.1-incubating/#considering-transactions[Reference Documentation - Considering Transactions]
 
 Deprecated credentialsDbLocation


[5/9] incubator-tinkerpop git commit: Deprecate local error metric in Gremlin Server

Posted by sp...@apache.org.
Deprecate local error metric in Gremlin Server

The local error metric was double counting errors as there was already a global error catching such things. Deprecated in case someone had extended these two classes and was using that class somehow.


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

Branch: refs/heads/master
Commit: bc1fc5e8931472a9c41b46dce03848a30cd7d59b
Parents: f34bde7
Author: Stephen Mallette <sp...@genoprime.com>
Authored: Wed Dec 16 11:57:45 2015 -0500
Committer: Stephen Mallette <sp...@genoprime.com>
Committed: Wed Dec 16 11:57:45 2015 -0500

----------------------------------------------------------------------
 .../gremlin/server/handler/OpSelectorHandler.java        | 10 +++++++++-
 .../gremlin/server/op/AbstractEvalOpProcessor.java       | 11 ++++++++++-
 2 files changed, 19 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/bc1fc5e8/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/handler/OpSelectorHandler.java
----------------------------------------------------------------------
diff --git a/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/handler/OpSelectorHandler.java b/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/handler/OpSelectorHandler.java
index 6ef65e2..816251f 100644
--- a/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/handler/OpSelectorHandler.java
+++ b/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/handler/OpSelectorHandler.java
@@ -50,6 +50,15 @@ import static com.codahale.metrics.MetricRegistry.name;
 @ChannelHandler.Sharable
 public class OpSelectorHandler extends MessageToMessageDecoder<RequestMessage> {
     private static final Logger logger = LoggerFactory.getLogger(OpSelectorHandler.class);
+
+    /**
+     * Captures the "error" count as a reportable metric for Gremlin Server.
+     *
+     * @deprecated As of release 3.1.1-incubating, not replaced. Direct usage is discouraged with sub-classes as
+     * error counts are captured more globally for error messages written down the pipeline to
+     * {@link GremlinResponseFrameEncoder}.
+     */
+    @Deprecated
     static final Meter errorMeter = MetricManager.INSTANCE.getMeter(name(GremlinServer.class, "errors"));
 
     private final Settings settings;
@@ -84,7 +93,6 @@ public class OpSelectorHandler extends MessageToMessageDecoder<RequestMessage> {
                 throw new OpProcessorException(errorMessage, ResponseMessage.build(msg).code(ResponseStatusCode.REQUEST_ERROR_INVALID_REQUEST_ARGUMENTS).result(errorMessage).create());
             }
         } catch (OpProcessorException ope) {
-            errorMeter.mark();
             logger.warn(ope.getMessage(), ope);
             ctx.writeAndFlush(ope.getResponseMessage());
         }

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/bc1fc5e8/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/op/AbstractEvalOpProcessor.java
----------------------------------------------------------------------
diff --git a/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/op/AbstractEvalOpProcessor.java b/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/op/AbstractEvalOpProcessor.java
index abaa8b5..3df9156 100644
--- a/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/op/AbstractEvalOpProcessor.java
+++ b/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/op/AbstractEvalOpProcessor.java
@@ -29,6 +29,7 @@ import org.apache.tinkerpop.gremlin.driver.ser.MessageTextSerializer;
 import org.apache.tinkerpop.gremlin.groovy.engine.GremlinExecutor;
 import org.apache.tinkerpop.gremlin.server.GraphManager;
 import org.apache.tinkerpop.gremlin.server.handler.Frame;
+import org.apache.tinkerpop.gremlin.server.handler.GremlinResponseFrameEncoder;
 import org.apache.tinkerpop.gremlin.server.handler.StateKey;
 import org.apache.tinkerpop.gremlin.structure.T;
 import org.apache.tinkerpop.gremlin.server.Context;
@@ -67,6 +68,15 @@ import static com.codahale.metrics.MetricRegistry.name;
 public abstract class AbstractEvalOpProcessor implements OpProcessor {
     private static final Logger logger = LoggerFactory.getLogger(AbstractEvalOpProcessor.class);
     public static final Timer evalOpTimer = MetricManager.INSTANCE.getTimer(name(GremlinServer.class, "op", "eval"));
+
+    /**
+     * Captures the "error" count as a reportable metric for Gremlin Server.
+     *
+     * @deprecated As of release 3.1.1-incubating, not replaced. Direct usage is discouraged with sub-classes as
+     * error counts are captured more globally for error messages written down the pipeline to
+     * {@link GremlinResponseFrameEncoder}.
+     */
+    @Deprecated
     static final Meter errorMeter = MetricManager.INSTANCE.getMeter(name(GremlinServer.class, "errors"));
 
     /**
@@ -320,7 +330,6 @@ public abstract class AbstractEvalOpProcessor implements OpProcessor {
                         .result(aggregate).create())));
             }
         } catch (Exception ex) {
-            errorMeter.mark();
             logger.warn("The result [{}] in the request {} could not be serialized and returned.", aggregate, msg.getRequestId(), ex);
             final String errorMessage = String.format("Error during serialization: %s",
                     ex.getCause() != null ? ex.getCause().getMessage() : ex.getMessage());


[6/9] incubator-tinkerpop git commit: Merge remote-tracking branch 'origin/master' into TINKERPOP-1035

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


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

Branch: refs/heads/master
Commit: 0e2700508774b807da209109bf305268e7a1b0d7
Parents: bc1fc5e a705c21
Author: Stephen Mallette <sp...@genoprime.com>
Authored: Tue Dec 29 13:50:40 2015 -0500
Committer: Stephen Mallette <sp...@genoprime.com>
Committed: Tue Dec 29 13:50:40 2015 -0500

----------------------------------------------------------------------
 CHANGELOG.asciidoc                              |   5 +
 README.asciidoc                                 |  12 +-
 docs/src/dev/developer/contributing.asciidoc    |   2 +
 docs/src/dev/developer/release.asciidoc         |   4 +-
 .../src/reference/gremlin-applications.asciidoc |  55 ++++++----
 docs/src/reference/implementations.asciidoc     |   5 +
 docs/src/reference/the-graphcomputer.asciidoc   |  11 +-
 .../tutorials/getting-started/index.asciidoc    |  52 ++++-----
 docs/static/images/business-gremlin.png         | Bin 0 -> 412520 bytes
 docs/static/images/quantum-gremlin-full.png     | Bin 0 -> 1877990 bytes
 .../computer/bulkloading/BulkLoader.java        |   8 +-
 .../bulkloading/BulkLoaderVertexProgram.java    |  10 +-
 .../bulkloading/IncrementalBulkLoader.java      |   8 +-
 .../computer/bulkloading/OneTimeBulkLoader.java | 109 +++++++++++++++++++
 ...remlinGroovyScriptEngineFileSandboxTest.java |   9 +-
 .../process/GroovyProcessComputerSuite.java     |   1 -
 .../gremlin/groovy/jsr223/sandbox.yaml          |  42 +++----
 .../customizer/AbstractSandboxExtension.groovy  |   2 +-
 .../PropertyExpressionEvaluator.groovy          |   2 +-
 .../customizer/TinkerPopSandboxExtension.groovy |   2 +-
 .../gremlin/groovy/engine/GremlinExecutor.java  |   3 +-
 .../server/handler/OpSelectorHandler.java       |   2 +-
 .../server/op/AbstractEvalOpProcessor.java      |  22 +++-
 .../server/op/control/ControlOpProcessor.java   |  18 +--
 .../server/op/session/SessionOpProcessor.java   |   6 +-
 .../server/op/standard/StandardOpProcessor.java |   6 +-
 .../server/GremlinDriverIntegrateTest.java      |  42 +++++++
 .../server/GremlinServerIntegrateTest.java      |  90 ++++++++++-----
 .../tinkerpop/gremlin/AbstractGremlinSuite.java |  25 +++--
 .../BulkLoaderVertexProgramTest.java            |  36 +++++-
 .../tinkergraph/structure/TinkerGraphTest.java  |   7 --
 31 files changed, 429 insertions(+), 167 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/0e270050/docs/src/reference/gremlin-applications.asciidoc
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/0e270050/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/handler/OpSelectorHandler.java
----------------------------------------------------------------------
diff --cc gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/handler/OpSelectorHandler.java
index 816251f,1c7e20c..432cecd
--- a/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/handler/OpSelectorHandler.java
+++ b/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/handler/OpSelectorHandler.java
@@@ -90,9 -81,10 +90,9 @@@ public class OpSelectorHandler extends 
              else {
                  // invalid op processor selected so write back an error by way of OpProcessorException.
                  final String errorMessage = String.format("Invalid OpProcessor requested [%s]", msg.getProcessor());
-                 throw new OpProcessorException(errorMessage, ResponseMessage.build(msg).code(ResponseStatusCode.REQUEST_ERROR_INVALID_REQUEST_ARGUMENTS).result(errorMessage).create());
+                 throw new OpProcessorException(errorMessage, ResponseMessage.build(msg).code(ResponseStatusCode.REQUEST_ERROR_INVALID_REQUEST_ARGUMENTS).statusMessage(errorMessage).create());
              }
          } catch (OpProcessorException ope) {
 -            errorMeter.mark();
              logger.warn(ope.getMessage(), ope);
              ctx.writeAndFlush(ope.getResponseMessage());
          }

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/0e270050/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/op/AbstractEvalOpProcessor.java
----------------------------------------------------------------------