private static Optional<Map<String, String>> validatedAliases(final RequestMessage message) throws OpProcessorException { final Optional<Map<String, String>> aliases = message.optionalArgs(Tokens.ARGS_ALIASES); if (!aliases.isPresent()) { final String msg = String.format("A message with [%s] op code requires a [%s] argument.", Tokens.OPS_BYTECODE, Tokens.ARGS_ALIASES); throw new OpProcessorException(msg, ResponseMessage.build(message).code(ResponseStatusCode.REQUEST_ERROR_INVALID_REQUEST_ARGUMENTS).statusMessage(msg).create()); } if (aliases.get().size() != 1 || !aliases.get().containsKey(Tokens.VAL_TRAVERSAL_SOURCE_ALIAS)) { final String msg = String.format("A message with [%s] op code requires the [%s] argument to be a Map containing one alias assignment named '%s'.", Tokens.OPS_BYTECODE, Tokens.ARGS_ALIASES, Tokens.VAL_TRAVERSAL_SOURCE_ALIAS); throw new OpProcessorException(msg, ResponseMessage.build(message).code(ResponseStatusCode.REQUEST_ERROR_INVALID_REQUEST_ARGUMENTS).statusMessage(msg).create()); } return aliases; }
private static Map<String, String> validateTraversalRequest(final RequestMessage message) throws OpProcessorException { if (!message.optionalArgs(Tokens.ARGS_GREMLIN).isPresent()) { final String msg = String.format("A message with [%s] op code requires a [%s] argument.", Tokens.OPS_BYTECODE, Tokens.ARGS_GREMLIN); throw new OpProcessorException(msg, ResponseMessage.build(message).code(ResponseStatusCode.REQUEST_ERROR_INVALID_REQUEST_ARGUMENTS).statusMessage(msg).create()); } return validatedAliases(message).get(); }
@Override protected Optional<ThrowingConsumer<Context>> validateEvalMessage(final RequestMessage message) throws OpProcessorException { super.validateEvalMessage(message); if (!message.optionalArgs(Tokens.ARGS_SESSION).isPresent()) { final String msg = String.format("A message with an [%s] op code requires a [%s] argument", Tokens.OPS_EVAL, Tokens.ARGS_SESSION); throw new OpProcessorException(msg, ResponseMessage.build(message).code(ResponseStatusCode.REQUEST_ERROR_INVALID_REQUEST_ARGUMENTS).statusMessage(msg).create()); } return Optional.empty(); }
/** * Uses a {@link LoadBalancingStrategy} to choose the best {@link Host} and then selects the best connection * from that host's connection pool. */ @Override protected Connection chooseConnection(final RequestMessage msg) throws TimeoutException, ConnectionException { final Iterator<Host> possibleHosts; if (msg.optionalArgs(Tokens.ARGS_HOST).isPresent()) { // TODO: not sure what should be done if unavailable - select new host and re-submit traversal? final Host host = (Host) msg.getArgs().get(Tokens.ARGS_HOST); msg.getArgs().remove(Tokens.ARGS_HOST); possibleHosts = IteratorUtils.of(host); } else { possibleHosts = this.cluster.loadBalancingStrategy().select(msg); } // you can get no possible hosts in more than a few situations. perhaps the servers are just all down. // or perhaps the client is not configured properly (disables ssl when ssl is enabled on the server). if (!possibleHosts.hasNext()) throw new TimeoutException("Timed out while waiting for an available host - check the client configuration and connectivity to the server if this message persists"); final Host bestHost = possibleHosts.next(); final ConnectionPool pool = hostConnectionPools.get(bestHost); return pool.borrowConnection(cluster.connectionPoolSettings().maxWaitForConnection, TimeUnit.MILLISECONDS); }
protected Optional<ThrowingConsumer<Context>> validateEvalMessage(final RequestMessage message) throws OpProcessorException { if (!message.optionalArgs(Tokens.ARGS_GREMLIN).isPresent()) { final String msg = String.format("A message with an [%s] op code requires a [%s] argument.", Tokens.OPS_EVAL, Tokens.ARGS_GREMLIN); throw new OpProcessorException(msg, ResponseMessage.build(message).code(ResponseStatusCode.REQUEST_ERROR_INVALID_REQUEST_ARGUMENTS).statusMessage(msg).create()); } if (message.optionalArgs(Tokens.ARGS_BINDINGS).isPresent()) { final Map bindings = (Map) message.getArgs().get(Tokens.ARGS_BINDINGS); if (IteratorUtils.anyMatch(bindings.keySet().iterator(), k -> null == k || !(k instanceof String))) { final String msg = String.format("The [%s] message is using one or more invalid binding keys - they must be of type String and cannot be null", Tokens.OPS_EVAL); throw new OpProcessorException(msg, ResponseMessage.build(message).code(ResponseStatusCode.REQUEST_ERROR_INVALID_REQUEST_ARGUMENTS).statusMessage(msg).create()); } final Set<String> badBindings = IteratorUtils.set(IteratorUtils.<String>filter(bindings.keySet().iterator(), INVALID_BINDINGS_KEYS::contains)); if (!badBindings.isEmpty()) { final String msg = String.format("The [%s] message supplies one or more invalid parameters key of [%s] - these are reserved names.", Tokens.OPS_EVAL, badBindings); throw new OpProcessorException(msg, ResponseMessage.build(message).code(ResponseStatusCode.REQUEST_ERROR_INVALID_REQUEST_ARGUMENTS).statusMessage(msg).create()); } // ignore control bindings that get passed in with the "#jsr223" prefix - those aren't used in compilation if (IteratorUtils.count(IteratorUtils.filter(bindings.keySet().iterator(), k -> !k.toString().startsWith("#jsr223"))) > maxParameters) { final String msg = String.format("The [%s] message contains %s bindings which is more than is allowed by the server %s configuration", Tokens.OPS_EVAL, bindings.size(), maxParameters); throw new OpProcessorException(msg, ResponseMessage.build(message).code(ResponseStatusCode.REQUEST_ERROR_INVALID_REQUEST_ARGUMENTS).statusMessage(msg).create()); } } return Optional.empty(); }
/** * 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(); } }
final Optional<UUID> sideEffect = msg.optionalArgs(Tokens.ARGS_SIDE_EFFECT); final Optional<String> sideEffectKey = msg.optionalArgs(Tokens.ARGS_SIDE_EFFECT_KEY); final Map<String, String> aliases = (Map<String, String>) msg.optionalArgs(Tokens.ARGS_ALIASES).get();
final int resultIterationBatchSize = (Integer) msg.optionalArgs(Tokens.ARGS_BATCH_SIZE) .orElse(settings.resultIterationBatchSize); List<Object> aggregate = new ArrayList<>(resultIterationBatchSize);
final int resultIterationBatchSize = (Integer) msg.optionalArgs(Tokens.ARGS_BATCH_SIZE) .orElse(settings.resultIterationBatchSize); List<Object> aggregate = new ArrayList<>(resultIterationBatchSize);
break; case Tokens.OPS_GATHER: final Optional<String> sideEffectForGather = message.optionalArgs(Tokens.ARGS_SIDE_EFFECT); 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); final Optional<String> sideEffectKey = message.optionalArgs(Tokens.ARGS_SIDE_EFFECT_KEY); 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); final Optional<String> sideEffectForKeys = message.optionalArgs(Tokens.ARGS_SIDE_EFFECT); 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); final Optional<UUID> sideEffect = msg.optionalArgs(Tokens.ARGS_SIDE_EFFECT); final TraversalSideEffects sideEffects = cache.getIfPresent(sideEffect.get()); final Optional<String> sideEffectForClose = message.optionalArgs(Tokens.ARGS_SIDE_EFFECT); 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); logger.debug("Close request {} for in thread {}", msg.getRequestId(), Thread.currentThread().getName()); final Optional<UUID> sideEffect = msg.optionalArgs(Tokens.ARGS_SIDE_EFFECT); cache.invalidate(sideEffect.get());
final Map<String, String> aliases = (Map<String, String>) msg.optionalArgs(Tokens.ARGS_ALIASES).get();
@Override protected Optional<ThrowingConsumer<Context>> validateEvalMessage(final RequestMessage message) throws OpProcessorException { super.validateEvalMessage(message); if (!message.optionalArgs(Tokens.ARGS_SESSION).isPresent()) { final String msg = String.format("A message with an [%s] op code requires a [%s] argument", Tokens.OPS_EVAL, Tokens.ARGS_SESSION); throw new OpProcessorException(msg, ResponseMessage.build(message).code(ResponseStatusCode.REQUEST_ERROR_INVALID_REQUEST_ARGUMENTS).statusMessage(msg).create()); } return Optional.empty(); }
private static Map<String, String> validateTraversalRequest(final RequestMessage message) throws OpProcessorException { if (!message.optionalArgs(Tokens.ARGS_GREMLIN).isPresent()) { final String msg = String.format("A message with [%s] op code requires a [%s] argument.", Tokens.OPS_BYTECODE, Tokens.ARGS_GREMLIN); throw new OpProcessorException(msg, ResponseMessage.build(message).code(ResponseStatusCode.REQUEST_ERROR_INVALID_REQUEST_ARGUMENTS).statusMessage(msg).create()); } return validatedAliases(message).get(); }
private static Optional<Map<String, String>> validatedAliases(final RequestMessage message) throws OpProcessorException { final Optional<Map<String, String>> aliases = message.optionalArgs(Tokens.ARGS_ALIASES); if (!aliases.isPresent()) { final String msg = String.format("A message with [%s] op code requires a [%s] argument.", Tokens.OPS_BYTECODE, Tokens.ARGS_ALIASES); throw new OpProcessorException(msg, ResponseMessage.build(message).code(ResponseStatusCode.REQUEST_ERROR_INVALID_REQUEST_ARGUMENTS).statusMessage(msg).create()); } if (aliases.get().size() != 1 || !aliases.get().containsKey(Tokens.VAL_TRAVERSAL_SOURCE_ALIAS)) { final String msg = String.format("A message with [%s] op code requires the [%s] argument to be a Map containing one alias assignment named '%s'.", Tokens.OPS_BYTECODE, Tokens.ARGS_ALIASES, Tokens.VAL_TRAVERSAL_SOURCE_ALIAS); throw new OpProcessorException(msg, ResponseMessage.build(message).code(ResponseStatusCode.REQUEST_ERROR_INVALID_REQUEST_ARGUMENTS).statusMessage(msg).create()); } return aliases; }
/** * Uses a {@link LoadBalancingStrategy} to choose the best {@link Host} and then selects the best connection * from that host's connection pool. */ @Override protected Connection chooseConnection(final RequestMessage msg) throws TimeoutException, ConnectionException { final Iterator<Host> possibleHosts; if (msg.optionalArgs(Tokens.ARGS_HOST).isPresent()) { // TODO: not sure what should be done if unavailable - select new host and re-submit traversal? final Host host = (Host) msg.getArgs().get(Tokens.ARGS_HOST); msg.getArgs().remove(Tokens.ARGS_HOST); possibleHosts = IteratorUtils.of(host); } else { possibleHosts = this.cluster.loadBalancingStrategy().select(msg); } // you can get no possible hosts in more than a few situations. perhaps the servers are just all down. // or perhaps the client is not configured properly (disables ssl when ssl is enabled on the server). if (!possibleHosts.hasNext()) throw new TimeoutException("Timed out while waiting for an available host - check the client configuration and connectivity to the server if this message persists"); final Host bestHost = possibleHosts.next(); final ConnectionPool pool = hostConnectionPools.get(bestHost); return pool.borrowConnection(cluster.connectionPoolSettings().maxWaitForConnection, TimeUnit.MILLISECONDS); }
private GraphTraversalSource traversal(Context context) throws OpProcessorException { RequestMessage msg = context.getRequestMessage(); GraphManager graphManager = context.getGraphManager(); Optional<Map<String, String>> aliasesOptional = msg.optionalArgs(Tokens.ARGS_ALIASES); String gAlias = aliasesOptional .map(aliases -> aliases.get(Tokens.VAL_TRAVERSAL_SOURCE_ALIAS)) .orElse(null); if (gAlias == null) { return graphManager.getGraphNames().stream() .sorted() .findFirst() .map(graphManager::getGraph) .map(Graph::traversal) .orElseThrow(() -> opProcessorException(msg, "No graphs found on the server")); } Graph graph = graphManager.getGraph(gAlias); if (graph != null) { return graph.traversal(); } TraversalSource traversalSource = graphManager.getTraversalSource(gAlias); if (traversalSource instanceof GraphTraversalSource) { return (GraphTraversalSource) traversalSource; } throw opProcessorException(msg, "Traversable alias '" + gAlias + "' not found"); }
/** * 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(); } }
protected Optional<ThrowingConsumer<Context>> validateEvalMessage(final RequestMessage message) throws OpProcessorException { if (!message.optionalArgs(Tokens.ARGS_GREMLIN).isPresent()) { final String msg = String.format("A message with an [%s] op code requires a [%s] argument.", Tokens.OPS_EVAL, Tokens.ARGS_GREMLIN); throw new OpProcessorException(msg, ResponseMessage.build(message).code(ResponseStatusCode.REQUEST_ERROR_INVALID_REQUEST_ARGUMENTS).statusMessage(msg).create()); } if (message.optionalArgs(Tokens.ARGS_BINDINGS).isPresent()) { final Map bindings = (Map) message.getArgs().get(Tokens.ARGS_BINDINGS); if (IteratorUtils.anyMatch(bindings.keySet().iterator(), k -> null == k || !(k instanceof String))) { final String msg = String.format("The [%s] message is using one or more invalid binding keys - they must be of type String and cannot be null", Tokens.OPS_EVAL); throw new OpProcessorException(msg, ResponseMessage.build(message).code(ResponseStatusCode.REQUEST_ERROR_INVALID_REQUEST_ARGUMENTS).statusMessage(msg).create()); } final Set<String> badBindings = IteratorUtils.set(IteratorUtils.<String>filter(bindings.keySet().iterator(), INVALID_BINDINGS_KEYS::contains)); if (!badBindings.isEmpty()) { final String msg = String.format("The [%s] message supplies one or more invalid parameters key of [%s] - these are reserved names.", Tokens.OPS_EVAL, badBindings); throw new OpProcessorException(msg, ResponseMessage.build(message).code(ResponseStatusCode.REQUEST_ERROR_INVALID_REQUEST_ARGUMENTS).statusMessage(msg).create()); } // ignore control bindings that get passed in with the "#jsr223" prefix - those aren't used in compilation if (IteratorUtils.count(IteratorUtils.filter(bindings.keySet().iterator(), k -> !k.toString().startsWith("#jsr223"))) > maxParameters) { final String msg = String.format("The [%s] message contains %s bindings which is more than is allowed by the server %s configuration", Tokens.OPS_EVAL, bindings.size(), maxParameters); throw new OpProcessorException(msg, ResponseMessage.build(message).code(ResponseStatusCode.REQUEST_ERROR_INVALID_REQUEST_ARGUMENTS).statusMessage(msg).create()); } } return Optional.empty(); }
final Optional<UUID> sideEffect = msg.optionalArgs(Tokens.ARGS_SIDE_EFFECT); final Optional<String> sideEffectKey = msg.optionalArgs(Tokens.ARGS_SIDE_EFFECT_KEY); final Map<String, String> aliases = (Map<String, String>) msg.optionalArgs(Tokens.ARGS_ALIASES).get();
break; case Tokens.OPS_GATHER: final Optional<String> sideEffectForGather = message.optionalArgs(Tokens.ARGS_SIDE_EFFECT); 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); final Optional<String> sideEffectKey = message.optionalArgs(Tokens.ARGS_SIDE_EFFECT_KEY); 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); final Optional<String> sideEffectForKeys = message.optionalArgs(Tokens.ARGS_SIDE_EFFECT); 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); final Optional<UUID> sideEffect = msg.optionalArgs(Tokens.ARGS_SIDE_EFFECT); final TraversalSideEffects sideEffects = cache.getIfPresent(sideEffect.get()); final Optional<String> sideEffectForClose = message.optionalArgs(Tokens.ARGS_SIDE_EFFECT); 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); logger.debug("Close request {} for in thread {}", msg.getRequestId(), Thread.currentThread().getName()); final Optional<UUID> sideEffect = msg.optionalArgs(Tokens.ARGS_SIDE_EFFECT); cache.invalidate(sideEffect.get());