.code(ResponseStatusCode.NO_CONTENT) .statusAttributes(generateStatusAttributes(ctx, msg, ResponseStatusCode.NO_CONTENT, itty, settings)) .create()); return;
rhc.writeAndFlush(ResponseMessage.build(msg).code(ResponseStatusCode.SERVER_ERROR_TIMEOUT) .statusMessage("Timeout during script evaluation triggered by TimedInterruptCustomizerProvider") .statusAttributeException(t).create()); } else if (t instanceof TimeoutException) { final String errorMessage = String.format("Script evaluation exceeded the configured threshold for request [%s]", msg); logger.warn(errorMessage, t); rhc.writeAndFlush(ResponseMessage.build(msg).code(ResponseStatusCode.SERVER_ERROR_TIMEOUT) .statusMessage(t.getMessage()) .statusAttributeException(t).create()); } else { final String errorMessage = String.format("The Gremlin statement that was submitted exceeds the maximum compilation size allowed by the JVM, please split it into multiple smaller statements - %s", trimMessage(msg)); logger.warn(errorMessage); rhc.writeAndFlush(ResponseMessage.build(msg).code(ResponseStatusCode.SERVER_ERROR_SCRIPT_EVALUATION) .statusMessage(errorMessage) .statusAttributeException(t).create()); } else { logger.warn(String.format("Exception processing a script on request [%s].", msg), t); rhc.writeAndFlush(ResponseMessage.build(msg).code(ResponseStatusCode.SERVER_ERROR_SCRIPT_EVALUATION) .statusMessage(t.getMessage()) .statusAttributeException(t).create());
.code(ResponseStatusCode.NO_CONTENT) .statusAttributes(generateStatusAttributes(ctx, msg, ResponseStatusCode.NO_CONTENT, itty, settings)) .create()); return;
rhc.writeAndFlush(ResponseMessage.build(msg).code(ResponseStatusCode.SERVER_ERROR_TIMEOUT) .statusMessage("Timeout during script evaluation triggered by TimedInterruptCustomizerProvider") .statusAttributeException(t).create()); } else if (t instanceof TimeoutException) { final String errorMessage = String.format("Script evaluation exceeded the configured threshold for request [%s]", msg); logger.warn(errorMessage, t); rhc.writeAndFlush(ResponseMessage.build(msg).code(ResponseStatusCode.SERVER_ERROR_TIMEOUT) .statusMessage(t.getMessage()) .statusAttributeException(t).create()); } else { final String errorMessage = String.format("The Gremlin statement that was submitted exceeds the maximum compilation size allowed by the JVM, please split it into multiple smaller statements - %s", trimMessage(msg)); logger.warn(errorMessage); rhc.writeAndFlush(ResponseMessage.build(msg).code(ResponseStatusCode.SERVER_ERROR_SCRIPT_EVALUATION) .statusMessage(errorMessage) .statusAttributeException(t).create()); } else { logger.warn(String.format("Exception processing a script on request [%s].", msg), t); rhc.writeAndFlush(ResponseMessage.build(msg).code(ResponseStatusCode.SERVER_ERROR_SCRIPT_EVALUATION) .statusMessage(t.getMessage()) .statusAttributeException(t).create());
.code(ResponseStatusCode.NO_CONTENT) .statusAttributes(generateStatusAttributes(ctx, msg, ResponseStatusCode.NO_CONTENT, itty, settings)) .create()); return;
logger.error("Could not deserialize the Traversal instance", ex); throw new OpProcessorException("Could not deserialize the Traversal instance", ResponseMessage.build(msg).code(ResponseStatusCode.SERVER_ERROR_SERIALIZATION) .statusMessage(ex.getMessage()) .statusAttributeException(ex).create()); final String errorMessage = String.format("A timeout occurred during traversal evaluation of [%s] - consider increasing the limit given to scriptEvaluationTimeout", msg); logger.warn(errorMessage); ctx.writeAndFlush(ResponseMessage.build(msg).code(ResponseStatusCode.SERVER_ERROR_TIMEOUT) .statusMessage(errorMessage) .statusAttributeException(ex).create()); onError(graph, context); } else { logger.warn(String.format("Exception processing a Traversal on iteration for request [%s].", msg.getRequestId()), ex); ctx.writeAndFlush(ResponseMessage.build(msg).code(ResponseStatusCode.SERVER_ERROR) .statusMessage(ex.getMessage()) .statusAttributeException(ex).create()); onError(graph, context); ctx.writeAndFlush(ResponseMessage.build(msg).code(ResponseStatusCode.SERVER_ERROR) .statusMessage(ex.getMessage()) .statusAttributeException(ex).create()); onError(graph, context); } finally {
if (!sideEffectForGather.isPresent()) { final String msg = String.format("A message with an [%s] op code requires a [%s] argument.", Tokens.OPS_GATHER, Tokens.ARGS_SIDE_EFFECT); throw new OpProcessorException(msg, ResponseMessage.build(message).code(ResponseStatusCode.REQUEST_ERROR_INVALID_REQUEST_ARGUMENTS).statusMessage(msg).create()); if (!sideEffectKey.isPresent()) { final String msg = String.format("A message with an [%s] op code requires a [%s] argument.", Tokens.OPS_GATHER, Tokens.ARGS_SIDE_EFFECT_KEY); throw new OpProcessorException(msg, ResponseMessage.build(message).code(ResponseStatusCode.REQUEST_ERROR_INVALID_REQUEST_ARGUMENTS).statusMessage(msg).create()); if (!sideEffectForKeys.isPresent()) { final String msg = String.format("A message with an [%s] op code requires a [%s] argument.", Tokens.OPS_GATHER, Tokens.ARGS_SIDE_EFFECT); throw new OpProcessorException(msg, ResponseMessage.build(message).code(ResponseStatusCode.REQUEST_ERROR_INVALID_REQUEST_ARGUMENTS).statusMessage(msg).create()); if (!sideEffectForClose.isPresent()) { final String msg = String.format("A message with an [%s] op code requires a [%s] argument.", Tokens.OPS_CLOSE, Tokens.ARGS_SIDE_EFFECT); throw new OpProcessorException(msg, ResponseMessage.build(message).code(ResponseStatusCode.REQUEST_ERROR_INVALID_REQUEST_ARGUMENTS).statusMessage(msg).create()); ctx.getChannelHandlerContext().writeAndFlush(ResponseMessage.build(message).code(ResponseStatusCode.NO_CONTENT).statusMessage(successMessage).create()); }; case Tokens.OPS_INVALID: final String msgInvalid = String.format("Message could not be parsed. Check the format of the request. [%s]", message); throw new OpProcessorException(msgInvalid, ResponseMessage.build(message).code(ResponseStatusCode.REQUEST_ERROR_MALFORMED_REQUEST).statusMessage(msgInvalid).create()); default: final String msgDefault = String.format("Message with op code [%s] is not recognized.", message.getOp()); throw new OpProcessorException(msgDefault, ResponseMessage.build(message).code(ResponseStatusCode.REQUEST_ERROR_MALFORMED_REQUEST).statusMessage(msgDefault).create());
final String errorMessage = String.format("Could not find side-effects for %s.", sideEffect.get()); logger.warn(errorMessage); ctx.writeAndFlush(ResponseMessage.build(msg).code(ResponseStatusCode.SERVER_ERROR).statusMessage(errorMessage).create()); onError(graph, context); return; final String errorMessage = String.format("Could not find side-effect key for %s in %s.", sideEffectKey.get(), sideEffect.get()); logger.warn(errorMessage); ctx.writeAndFlush(ResponseMessage.build(msg).code(ResponseStatusCode.SERVER_ERROR).statusMessage(errorMessage).create()); onError(graph, context); return; } catch (Exception ex) { logger.warn(String.format("Exception processing a side-effect on iteration for request [%s].", msg.getRequestId()), ex); ctx.writeAndFlush(ResponseMessage.build(msg).code(ResponseStatusCode.SERVER_ERROR) .statusMessage(ex.getMessage()) .statusAttributeException(ex).create()); onError(graph, context); return; } catch (Exception ex) { logger.warn(String.format("Exception processing a side-effect on request [%s].", msg.getRequestId()), ex); ctx.writeAndFlush(ResponseMessage.build(msg).code(ResponseStatusCode.SERVER_ERROR) .statusMessage(ex.getMessage()) .statusAttributeException(ex).create()); onError(graph, context); } finally { timerContext.stop();
request.set(requestMessage); final ResponseMessage authenticate = ResponseMessage.build(requestMessage) .code(ResponseStatusCode.AUTHENTICATE).create(); ctx.writeAndFlush(authenticate); } else { } else { final ResponseMessage error = ResponseMessage.build(request.get()) .statusMessage("Incorrect type for : " + Tokens.ARGS_SASL + " - base64 encoded String is expected") .code(ResponseStatusCode.REQUEST_ERROR_MALFORMED_REQUEST).create(); ctx.writeAndFlush(error); return; metadata.put(Tokens.ARGS_SASL, BASE64_ENCODER.encodeToString(saslMessage)); final ResponseMessage authenticate = ResponseMessage.build(requestMessage) .statusAttributes(metadata) .code(ResponseStatusCode.AUTHENTICATE).create(); ctx.writeAndFlush(authenticate); .statusMessage(ae.getMessage()) .code(ResponseStatusCode.UNAUTHORIZED).create(); ctx.writeAndFlush(error); .statusMessage("Failed to authenticate") .code(ResponseStatusCode.UNAUTHORIZED).create(); ctx.writeAndFlush(error);
final String errorMessage = String.format("Error during serialization: %s", ExceptionHelper.getMessageFromExceptionOrCause(ex)); final ResponseMessage error = ResponseMessage.build(o.getRequestId()) .statusMessage(errorMessage) .statusAttributeException(ex) .code(ResponseStatusCode.SERVER_ERROR_SERIALIZATION).create(); if (useBinary) { objects.add(serializer.serializeResponseAsBinary(error, ctx.alloc()));
aliasKv.getKey(), aliasKv.getValue(), aliasKv.getValue()); throw new OpProcessorException(error, ResponseMessage.build(msg) .code(ResponseStatusCode.REQUEST_ERROR_INVALID_REQUEST_ARGUMENTS).statusMessage(error).create()); final String error = "Gremlin Server is configured with strictTransactionManagement as 'true' - the 'aliases' arguments must be provided"; throw new OpProcessorException(error, ResponseMessage.build(msg) .code(ResponseStatusCode.REQUEST_ERROR_INVALID_REQUEST_ARGUMENTS).statusMessage(error).create());
aliasKv.getKey(), aliasKv.getValue(), aliasKv.getValue()); throw new OpProcessorException(error, ResponseMessage.build(msg) .code(ResponseStatusCode.REQUEST_ERROR_INVALID_REQUEST_ARGUMENTS).statusMessage(error).create());
.code(ResponseStatusCode.FORBIDDEN).statusMessage(saslException.getMessage()).create(); channelHandlerContext.fireChannelRead(clientSideError); return;
/** * Session based requests accept a "close" operator in addition to "eval". A close will trigger the session to be * killed and any uncommitted transaction to be rolled-back. */ @Override public Optional<ThrowingConsumer<Context>> selectOther(final RequestMessage requestMessage) throws OpProcessorException { if (requestMessage.getOp().equals(Tokens.OPS_CLOSE)) { // this must be an in-session request if (!requestMessage.optionalArgs(Tokens.ARGS_SESSION).isPresent()) { final String msg = String.format("A message with an [%s] op code requires a [%s] argument", Tokens.OPS_CLOSE, Tokens.ARGS_SESSION); throw new OpProcessorException(msg, ResponseMessage.build(requestMessage).code(ResponseStatusCode.REQUEST_ERROR_INVALID_REQUEST_ARGUMENTS).statusMessage(msg).create()); } final boolean force = requestMessage.<Boolean>optionalArgs(Tokens.ARGS_FORCE).orElse(false); return Optional.of(ctx -> { // validate the session is present and then remove it if it is. final Session sessionToClose = sessions.get(requestMessage.getArgs().get(Tokens.ARGS_SESSION).toString()); if (null == sessionToClose) { final String msg = String.format("There was no session named %s to close", requestMessage.getArgs().get(Tokens.ARGS_SESSION).toString()); throw new OpProcessorException(msg, ResponseMessage.build(requestMessage).code(ResponseStatusCode.REQUEST_ERROR_INVALID_REQUEST_ARGUMENTS).statusMessage(msg).create()); } sessionToClose.manualKill(force); // send back a confirmation of the close ctx.getChannelHandlerContext().writeAndFlush(ResponseMessage.build(requestMessage) .code(ResponseStatusCode.NO_CONTENT) .create()); }); } else { return Optional.empty(); } }
if (useBinary) { return new Frame(serializer.serializeResponseAsBinary(ResponseMessage.build(msg) .code(code) .statusAttributes(statusAttributes) .responseMetaData(responseMetaData) .result(aggregate).create(), ctx.alloc())); } else { .code(code) .statusAttributes(statusAttributes) .responseMetaData(responseMetaData) .result(aggregate).create())); final String errorMessage = String.format("Error during serialization: %s", ExceptionHelper.getMessageFromExceptionOrCause(ex)); final ResponseMessage error = ResponseMessage.build(msg.getRequestId()) .statusMessage(errorMessage) .statusAttributeException(ex) .code(ResponseStatusCode.SERVER_ERROR_SERIALIZATION).create(); rhc.writeAndFlush(error); throw ex;
/** * A generalized implementation of the "eval" operation. It handles script evaluation and iteration of results * so as to write {@link ResponseMessage} objects down the Netty pipeline. It also handles script timeouts, * iteration timeouts, metrics and building bindings. Note that result iteration is delegated to the * {@link #handleIterator} method, so those extending this class could override that method for better control * over result iteration. * * @param context The current Gremlin Server {@link Context} * @param gremlinExecutorSupplier A function that returns the {@link GremlinExecutor} to use in executing the * script evaluation. * @param bindingsSupplier A function that returns the {@link Bindings} to provide to the * {@link GremlinExecutor#eval} method. * @see #evalOpInternal(ResponseHandlerContext, Supplier, BindingSupplier) */ protected void evalOpInternal(final Context context, final Supplier<GremlinExecutor> gremlinExecutorSupplier, final BindingSupplier bindingsSupplier) throws OpProcessorException { final ResponseHandlerContext rhc = new ResponseHandlerContext(context); try { evalOpInternal(rhc, gremlinExecutorSupplier, bindingsSupplier); } catch (Exception ex) { // Exceptions may occur on after the script started executing, therefore corresponding errors must be // reported via the ResponseHandlerContext. logger.warn("Unable to process script evaluation request: " + ex, ex); rhc.writeAndFlush(ResponseMessage.build(context.getRequestMessage()) .code(ResponseStatusCode.SERVER_ERROR) .statusAttributeException(ex) .statusMessage(ex.getMessage()).create()); } }
@Override public ByteBuf serializeResponseAsBinary(final ResponseMessage responseMessage, final ByteBufAllocator allocator) throws SerializationException { ByteBuf encodedMessage = null; try { final Kryo kryo = kryoThreadLocal.get(); try (final ByteArrayOutputStream baos = new ByteArrayOutputStream()) { final Output output = new Output(baos, bufferSize); final ResponseMessage msgToWrite = !serializeToString ? responseMessage : ResponseMessage.build(responseMessage.getRequestId()) .code(responseMessage.getStatus().getCode()) .statusAttributes(responseMessage.getStatus().getAttributes()) .responseMetaData(responseMessage.getResult().getMeta()) .result(serializeResultToString(responseMessage)) .statusMessage(responseMessage.getStatus().getMessage()).create(); kryo.writeObject(output, msgToWrite); final long size = output.total(); if (size > Integer.MAX_VALUE) throw new SerializationException(String.format("Message size of %s exceeds allocatable space", size)); output.flush(); encodedMessage = allocator.buffer((int) size); encodedMessage.writeBytes(baos.toByteArray()); } return encodedMessage; } catch (Exception ex) { if (encodedMessage != null) ReferenceCountUtil.release(encodedMessage); logger.warn(String.format("Response [%s] could not be serialized by %s.", responseMessage, AbstractGryoMessageSerializerV3d0.class.getName()), ex); throw new SerializationException(ex); } }
@Override protected void channelRead0(final ChannelHandlerContext ctx, final Pair<RequestMessage, ThrowingConsumer<Context>> objects) throws Exception { final RequestMessage msg = objects.getValue0(); final ThrowingConsumer<Context> op = objects.getValue1(); final Context gremlinServerContext = new Context(msg, ctx, settings, graphManager, gremlinExecutor, scheduledExecutorService); try { op.accept(gremlinServerContext); } catch (OpProcessorException ope) { // Ops may choose to throw OpProcessorException or write the error ResponseMessage down the line // themselves logger.warn(ope.getMessage(), ope); ctx.writeAndFlush(ope.getResponseMessage()); } catch (Exception ex) { // It is possible that an unplanned exception might raise out of an OpProcessor execution. Build a general // error to send back to the client logger.warn(ex.getMessage(), ex); ctx.writeAndFlush(ResponseMessage.build(msg) .code(ResponseStatusCode.SERVER_ERROR) .statusAttributeException(ex) .statusMessage(ex.getMessage()).create()); } finally { ReferenceCountUtil.release(objects); } } }