@Override public RequestMessage createObject(final Map<String, Object> data) { final Map<String, Object> args = (Map<String, Object>) data.get(SerTokens.TOKEN_ARGS); RequestMessage.Builder builder = RequestMessage.build(data.get(SerTokens.TOKEN_OP).toString()) .overrideRequestId(UUID.fromString(data.get(SerTokens.TOKEN_REQUEST).toString())); if (data.containsKey(SerTokens.TOKEN_PROCESSOR)) builder = builder.processor(data.get(SerTokens.TOKEN_PROCESSOR).toString()); if (args != null) { for (Map.Entry<String, Object> kv : args.entrySet()) { builder = builder.addArg(kv.getKey(), kv.getValue()); } } return builder.create(); } }
/** * Used to decrease the size of a Gremlin script that triggered a "method too large" exception so that it * doesn't log a massive text string nor return a large error message. */ private RequestMessage trimMessage(final RequestMessage msg) { final RequestMessage trimmedMsg = RequestMessage.from(msg).create(); if (trimmedMsg.getArgs().containsKey(Tokens.ARGS_GREMLIN)) trimmedMsg.getArgs().put(Tokens.ARGS_GREMLIN, trimmedMsg.getArgs().get(Tokens.ARGS_GREMLIN).toString().substring(0, 1021) + "..."); return trimmedMsg; }
@Override public CompletableFuture<ResultSet> submitAsync(final RequestMessage msg) { final RequestMessage.Builder builder = RequestMessage.from(msg); // only add aliases which aren't already present. if they are present then they represent request level // overrides which should be mucked with if (!aliases.isEmpty()) { final Map original = (Map) msg.getArgs().getOrDefault(Tokens.ARGS_ALIASES, Collections.emptyMap()); aliases.forEach((k,v) -> { if (!original.containsKey(k)) builder.addArg(Tokens.ARGS_ALIASES, aliases); }); } return super.submitAsync(builder.create()); }
/** * Used to decrease the size of a Gremlin script that triggered a "method too large" exception so that it * doesn't log a massive text string nor return a large error message. */ private RequestMessage trimMessage(final RequestMessage msg) { final RequestMessage trimmedMsg = RequestMessage.from(msg).create(); if (trimmedMsg.getArgs().containsKey(Tokens.ARGS_GREMLIN)) trimmedMsg.getArgs().put(Tokens.ARGS_GREMLIN, trimmedMsg.getArgs().get(Tokens.ARGS_GREMLIN).toString().substring(0, 1021) + "..."); return trimmedMsg; }
requestMessage = RequestMessage.build("authentication"). overrideRequestId(UUID.fromString("cb682578-9d92-4499-9ebc-5c6aa73c5397")). add("saslMechanism", "PLAIN", "sasl", "AHN0ZXBocGhlbgBwYXNzd29yZA==").create(); addRequestMessageEntry(requestMessage, "Authentication Response", "The following `RequestMessage` is an example of the response that should be made to a SASL-based authentication challenge."); requestMessage = RequestMessage.build("eval").processor("session"). overrideRequestId(UUID.fromString("cb682578-9d92-4499-9ebc-5c6aa73c5397")). add("gremlin", "g.V(x)", "bindings", requestBindings, "language", "gremlin-groovy", "session", UUID.fromString("41d2e28a-20a4-4ab0-b379-d810dede3786")).create(); addRequestMessageEntry(requestMessage, "Session Eval", "The following `RequestMessage` is an example of a simple session request for a script evaluation with parameters."); requestMessage = RequestMessage.build("eval").processor("session"). overrideRequestId(UUID.fromString("cb682578-9d92-4499-9ebc-5c6aa73c5397")). add("gremlin", "social.V(x)", "bindings", requestBindings, "language", "gremlin-groovy", "aliases", requestAliases, "session", UUID.fromString("41d2e28a-20a4-4ab0-b379-d810dede3786")).create(); addRequestMessageEntry(requestMessage, "Session Eval Aliased", "The following `RequestMessage` is an example of a session request for a script evaluation with an alias that binds the `TraversalSource` of \"g\" to \"social\"."); requestMessage = RequestMessage.build("close").processor("session"). overrideRequestId(UUID.fromString("cb682578-9d92-4499-9ebc-5c6aa73c5397")). add("session", UUID.fromString("41d2e28a-20a4-4ab0-b379-d810dede3786")).create(); addRequestMessageEntry(requestMessage, "Session Close", "The following `RequestMessage` is an example of a request to close a session."); requestMessage = RequestMessage.build("eval"). overrideRequestId(UUID.fromString("cb682578-9d92-4499-9ebc-5c6aa73c5397")). add("gremlin", "g.V(x)", "bindings", requestBindings, "language", "gremlin-groovy").create(); addRequestMessageEntry(requestMessage, "Sessionless Eval", "The following `RequestMessage` is an example of a simple sessionless request for a script evaluation with parameters."); requestMessage = RequestMessage.build("eval"). overrideRequestId(UUID.fromString("cb682578-9d92-4499-9ebc-5c6aa73c5397")). add("gremlin", "social.V(x)", "bindings", requestBindings, "language", "gremlin-groovy", "aliases", requestAliases).create(); addRequestMessageEntry(requestMessage, "Sessionless Eval Aliased", "The following `RequestMessage` is an example of a sessionless request for a script evaluation with an alias that binds the `TraversalSource` of \"g\" to \"social\".");
final boolean forceClose = client.getSettings().getSession().get().isForceClosed(); final RequestMessage closeMessage = client.buildMessage( RequestMessage.build(Tokens.OPS_CLOSE).addArg(Tokens.ARGS_FORCE, forceClose)).create();
evaluateChallenge(subject, saslClient, BASE64_DECODER.decode(base64sasl)))); channelHandlerContext.writeAndFlush(messageBuilder.create()); } else { channelHandlerContext.fireChannelRead(response);
.addArg(Tokens.ARGS_SIDE_EFFECT_KEY, key) .addArg(Tokens.ARGS_HOST, host) .processor("traversal").create(); try { final Result result = client.submitAsync(msg).get().all().get().get(0);
@Override public Set<String> keys() { // wait for the read to complete (i.e. iteration on the server) before allowing the caller to get the // side-effect. calling prior to this will result in the side-effect not being found. of course, the // bad part here is that the method blocks indefinitely waiting for the result, but it prevents the // test failure problems that happen on slower systems. in practice, it's unlikely that a user would // try to get a side-effect prior to iteration, but since the API allows it, this at least prevents // the error. ready.join(); if (closed && !retrievedAllKeys) throw new IllegalStateException("Traversal has been closed - side-effect keys cannot be retrieved"); if (!retrievedAllKeys) { // specify the ARGS_HOST so that the LoadBalancingStrategy is subverted and the connection is forced // from the specified host (i.e. the host from the previous request as that host will hold the side-effects) final RequestMessage msg = RequestMessage.build(Tokens.OPS_KEYS) .addArg(Tokens.ARGS_SIDE_EFFECT, serverSideEffect) .addArg(Tokens.ARGS_HOST, host) .processor("traversal").create(); try { if (keys.equals(Collections.emptySet())) keys = new HashSet<>(); client.submitAsync(msg).get().all().get().forEach(r -> keys.add(r.getString())); // only need to retrieve all keys once retrievedAllKeys = true; } catch (Exception ex) { final Throwable root = ExceptionUtils.getRootCause(ex); throw new RuntimeException("Could not get keys", null == root ? ex : root); } } return keys; }
@Override public RequestMessage deserializeRequest(final ByteBuf msg) throws SerializationException { try { final Kryo kryo = kryoThreadLocal.get(); final byte[] payload = new byte[msg.readableBytes()]; msg.readBytes(payload); try (final Input input = new Input(payload)) { // by the time the message gets here, the mime length/type have been already read, so this part just // needs to process the payload. final UUID id = kryo.readObject(input, UUID.class); final String processor = input.readString(); final String op = input.readString(); final RequestMessage.Builder builder = RequestMessage.build(op) .overrideRequestId(id) .processor(processor); final Map<String, Object> args = kryo.readObject(input, HashMap.class); args.forEach(builder::addArg); return builder.create(); } } catch (Exception ex) { logger.warn(String.format("Request [%s] could not be deserialized by %s.", msg, AbstractGryoMessageSerializerV1d0.class.getName()), ex); throw new SerializationException(ex); } }
/** * Attempt to reconnect to the {@link Host} that was previously marked as unavailable. This method gets called * as part of a schedule in {@link Host} to periodically try to create working connections. */ private boolean tryReconnect(final Host h) { logger.debug("Trying to re-establish connection on {}", host); Connection connection = null; try { connection = borrowConnection(cluster.connectionPoolSettings().maxWaitForConnection, TimeUnit.MILLISECONDS); final RequestMessage ping = client.buildMessage(cluster.validationRequest()).create(); final CompletableFuture<ResultSet> f = new CompletableFuture<>(); connection.write(ping, f); f.get().all().get(); // host is reconnected and a connection is now available this.cluster.loadBalancingStrategy().onAvailable(host); return true; } catch (Exception ex) { logger.debug("Failed reconnect attempt on {}", host); if (connection != null) definitelyDestroyConnection(connection); return false; } }
/** * The asynchronous version of {@link #submit(String, RequestOptions)}} where the returned future will complete when the * write of the request completes. * * @param gremlin the gremlin script to execute * @param options the options to supply for this request */ public CompletableFuture<ResultSet> submitAsync(final String gremlin, final RequestOptions options) { final int batchSize = options.getBatchSize().orElse(cluster.connectionPoolSettings().resultIterationBatchSize); // need to call buildMessage() right away to get client specific configurations, that way request specific // ones can override as needed final RequestMessage.Builder request = buildMessage(RequestMessage.build(Tokens.OPS_EVAL)) .add(Tokens.ARGS_GREMLIN, gremlin) .add(Tokens.ARGS_BATCH_SIZE, batchSize); // apply settings if they were made available options.getTimeout().ifPresent(timeout -> request.add(Tokens.ARGS_SCRIPT_EVAL_TIMEOUT, timeout)); options.getParameters().ifPresent(params -> request.addArg(Tokens.ARGS_BINDINGS, params)); options.getAliases().ifPresent(aliases -> request.addArg(Tokens.ARGS_ALIASES, aliases)); return submitAsync(request.create()); }
@Override public void close() throws Exception { if (!closed) { final RequestMessage msg = RequestMessage.build(Tokens.OPS_CLOSE) .addArg(Tokens.ARGS_SIDE_EFFECT, serverSideEffect) .addArg(Tokens.ARGS_HOST, host) .processor("traversal").create(); try { client.submitAsync(msg).get(); closed = true; } catch (Exception ex) { final Throwable root = ExceptionUtils.getRootCause(ex); throw new RuntimeException("Error on closing side effects", null == root ? ex : root); } } }
public CompletableFuture<List<ResponseMessage>> submitAsync(final RequestMessage requestMessage) throws Exception; }
public default void submit(final String gremlin, final Consumer<ResponseMessage> callback) throws Exception { submit(RequestMessage.build(Tokens.OPS_EVAL).addArg(Tokens.ARGS_GREMLIN, gremlin).create(), callback); }
public List<ResponseMessage> submit(final RequestMessage requestMessage) throws Exception;
@Override public <I extends InputShim> RequestMessage read(final KryoShim<I, ?> kryo, final I input, final Class<RequestMessage> aClass) { final UUID id = kryo.readObject(input, UUID.class); final String processor = input.readString(); final String op = input.readString(); final RequestMessage.Builder builder = RequestMessage.build(op) .overrideRequestId(id) .processor(processor); final Map<String, Object> args = kryo.readObject(input, HashMap.class); args.forEach(builder::addArg); return builder.create(); } }
@Benchmark public RequestMessage testInstanceCreation() { return RequestMessage.build("a").overrideRequestId(id).processor("b").create(); } }
@Override public CompletableFuture<ResultSet> submitAsync(final Bytecode bytecode) { try { return submitAsync(buildMessage(RequestMessage.build(Tokens.OPS_BYTECODE) .processor("traversal").addArg(Tokens.ARGS_GREMLIN, bytecode)).create()); } catch (Exception ex) { throw new RuntimeException(ex); } }
public RequestMessage readValue(final ByteBuf buffer, final GraphBinaryReader context) throws SerializationException { final int version = buffer.readByte(); assert version >>> 31 == 1; final UUID id = context.readValue(buffer, UUID.class, false); final String op = context.readValue(buffer, String.class, false); final String processor = context.readValue(buffer, String.class, false); final RequestMessage.Builder builder = RequestMessage.build(op).overrideRequestId(id).processor(processor); final Map<String, Object> args = context.readValue(buffer, Map.class, false); args.forEach(builder::addArg); return builder.create(); }