blob: 43014ce6dd47f72ccd19ac5dab3c56b678e8a94c [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.tinkerpop.gremlin.driver;
import org.apache.tinkerpop.gremlin.driver.ser.GryoMessageSerializerV1d0;
import org.apache.commons.configuration.Configuration;
import org.apache.tinkerpop.gremlin.driver.ser.GraphSONMessageSerializerV1d0;
import org.apache.tinkerpop.gremlin.util.iterator.IteratorUtils;
import org.yaml.snakeyaml.TypeDescription;
import org.yaml.snakeyaml.Yaml;
import org.yaml.snakeyaml.constructor.Constructor;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.Properties;
import java.util.stream.Collectors;
/**
* Settings for the {@link Cluster} and its related components.
*
* @author Stephen Mallette (http://stephen.genoprime.com)
*/
final class Settings {
/**
* The port of the Gremlin Server to connect to which defaults to {@code 8192}. The same port will be applied for
* all {@link #hosts}.
*/
public int port = 8182;
/**
* The list of hosts that the driver will connect to.
*/
public List<String> hosts = new ArrayList<>();
/**
* The serializer that will be used when communicating with the server. Note that serializer settings should match
* what is available on the server.
*/
public SerializerSettings serializer = new SerializerSettings();
/**
* Settings for connections and connection pool.
*/
public ConnectionPoolSettings connectionPool = new ConnectionPoolSettings();
/**
* The size of the thread pool defaulted to the number of available processors.
*/
public int nioPoolSize = Runtime.getRuntime().availableProcessors();
/**
* The number of worker threads defaulted to the number of available processors * 2.
*/
public int workerPoolSize = Runtime.getRuntime().availableProcessors() * 2;
/**
* The username to submit on requests that require authentication.
*/
public String username = null;
/**
* The password to submit on requests that require authentication.
*/
public String password = null;
/**
* The JAAS to submit on requests that require authentication.
*/
public String jaasEntry = null;
/**
* The JAAS protocol to submit on requests that require authentication.
*/
public String protocol = null;
/**
* Read configuration from a file into a new {@link Settings} object.
*
* @param stream an input stream containing a Gremlin Server YAML configuration
*/
public static Settings read(final InputStream stream) {
Objects.requireNonNull(stream);
final Constructor constructor = new Constructor(Settings.class);
final TypeDescription settingsDescription = new TypeDescription(Settings.class);
settingsDescription.putListPropertyType("hosts", String.class);
settingsDescription.putListPropertyType("serializers", SerializerSettings.class);
constructor.addTypeDescription(settingsDescription);
final Yaml yaml = new Yaml(constructor);
return yaml.loadAs(stream, Settings.class);
}
/**
* Read configuration from a file into a new {@link Settings} object.
*/
public static Settings from(final Configuration conf) {
final Settings settings = new Settings();
if (conf.containsKey("port"))
settings.port = conf.getInt("port");
if (conf.containsKey("nioPoolSize"))
settings.nioPoolSize = conf.getInt("nioPoolSize");
if (conf.containsKey("workerPoolSize"))
settings.workerPoolSize = conf.getInt("workerPoolSize");
if (conf.containsKey("username"))
settings.username = conf.getString("username");
if (conf.containsKey("password"))
settings.password = conf.getString("password");
if (conf.containsKey("jaasEntry"))
settings.jaasEntry = conf.getString("jaasEntry");
if (conf.containsKey("protocol"))
settings.protocol = conf.getString("protocol");
if (conf.containsKey("hosts"))
settings.hosts = conf.getList("hosts").stream().map(Object::toString).collect(Collectors.toList());
if (conf.containsKey("serializer.className")) {
final SerializerSettings serializerSettings = new SerializerSettings();
final Configuration serializerConf = conf.subset("serializer");
if (serializerConf.containsKey("className"))
serializerSettings.className = serializerConf.getString("className");
final Configuration serializerConfigConf = conf.subset("serializer.config");
if (IteratorUtils.count(serializerConfigConf.getKeys()) > 0) {
final Map<String,Object> m = new HashMap<>();
serializerConfigConf.getKeys().forEachRemaining(name -> {
m.put(name, serializerConfigConf.getProperty(name));
});
serializerSettings.config = m;
}
settings.serializer = serializerSettings;
}
final Configuration connectionPoolConf = conf.subset("connectionPool");
if (IteratorUtils.count(connectionPoolConf.getKeys()) > 0) {
final ConnectionPoolSettings cpSettings = new ConnectionPoolSettings();
if (connectionPoolConf.containsKey("channelizer"))
cpSettings.channelizer = connectionPoolConf.getString("channelizer");
if (connectionPoolConf.containsKey("enableSsl"))
cpSettings.enableSsl = connectionPoolConf.getBoolean("enableSsl");
if (connectionPoolConf.containsKey("trustCertChainFile"))
cpSettings.trustCertChainFile = connectionPoolConf.getString("trustCertChainFile");
if (connectionPoolConf.containsKey("minSize"))
cpSettings.minSize = connectionPoolConf.getInt("minSize");
if (connectionPoolConf.containsKey("maxSize"))
cpSettings.maxSize = connectionPoolConf.getInt("maxSize");
if (connectionPoolConf.containsKey("minSimultaneousUsagePerConnection"))
cpSettings.minSimultaneousUsagePerConnection = connectionPoolConf.getInt("minSimultaneousUsagePerConnection");
if (connectionPoolConf.containsKey("maxSimultaneousUsagePerConnection"))
cpSettings.maxSimultaneousUsagePerConnection = connectionPoolConf.getInt("maxSimultaneousUsagePerConnection");
if (connectionPoolConf.containsKey("maxInProcessPerConnection"))
cpSettings.maxInProcessPerConnection = connectionPoolConf.getInt("maxInProcessPerConnection");
if (connectionPoolConf.containsKey("minInProcessPerConnection"))
cpSettings.minInProcessPerConnection = connectionPoolConf.getInt("minInProcessPerConnection");
if (connectionPoolConf.containsKey("maxWaitForConnection"))
cpSettings.maxWaitForConnection = connectionPoolConf.getInt("maxWaitForConnection");
if (connectionPoolConf.containsKey("maxContentLength"))
cpSettings.maxContentLength = connectionPoolConf.getInt("maxContentLength");
if (connectionPoolConf.containsKey("reconnectInterval"))
cpSettings.reconnectInterval = connectionPoolConf.getInt("reconnectInterval");
if (connectionPoolConf.containsKey("reconnectInitialDelay"))
cpSettings.reconnectInitialDelay = connectionPoolConf.getInt("reconnectInitialDelay");
if (connectionPoolConf.containsKey("resultIterationBatchSize"))
cpSettings.resultIterationBatchSize = connectionPoolConf.getInt("resultIterationBatchSize");
settings.connectionPool = cpSettings;
}
return settings;
}
static class ConnectionPoolSettings {
/**
* Determines if SSL should be enabled or not. If enabled on the server then it must be enabled on the client.
*/
public boolean enableSsl = false;
/**
* The trusted certificate in PEM format.
*/
public String trustCertChainFile = null;
/**
* The X.509 certificate chain file in PEM format.
*/
public String keyCertChainFile = null;
/**
* The PKCS#8 private key file in PEM format.
*/
public String keyFile = null;
/**
* The password of the {@link #keyFile}, or {@code null} if it's not password-protected.
*/
public String keyPassword = null;
/**
* The minimum size of a connection pool for a {@link Host}. By default this is set to 2.
*/
public int minSize = ConnectionPool.MIN_POOL_SIZE;
/**
* The maximum size of a connection pool for a {@link Host}. By default this is set to 8.
*/
public int maxSize = ConnectionPool.MAX_POOL_SIZE;
/**
* A connection under low use can be destroyed. This setting determines the threshold for determining when
* that connection can be released and is defaulted to 8.
*/
public int minSimultaneousUsagePerConnection = ConnectionPool.MIN_SIMULTANEOUS_USAGE_PER_CONNECTION;
/**
* If a connection is over used, then it might mean that is necessary to expand the pool by adding a new
* connection. This setting determines the threshold for a connections over use and is defaulted to 16
*/
public int maxSimultaneousUsagePerConnection = ConnectionPool.MAX_SIMULTANEOUS_USAGE_PER_CONNECTION;
/**
* The maximum number of requests in flight on a connection where the default is 4.
*/
public int maxInProcessPerConnection = Connection.MAX_IN_PROCESS;
/**
* A connection has available in-process requests which is calculated by subtracting the number of current
* in-flight requests on a connection and subtracting that from the {@link #maxInProcessPerConnection}. When
* that number drops below this configuration setting, the connection is recommended for replacement. The
* default for this setting is 1.
*/
public int minInProcessPerConnection = Connection.MIN_IN_PROCESS;
/**
* The amount of time in milliseconds to wait for a new connection before timing out where the default value
* is 3000.
*/
public int maxWaitForConnection = Connection.MAX_WAIT_FOR_CONNECTION;
/**
* If the connection is using a "session" this setting represents the amount of time in milliseconds to wait
* for that session to close before timing out where the default value is 3000. Note that the server will
* eventually clean up dead sessions itself on expiration of the session or during shutdown.
*/
public int maxWaitForSessionClose = Connection.MAX_WAIT_FOR_SESSION_CLOSE;
/**
* The maximum length in bytes that a message can be sent to the server. This number can be no greater than
* the setting of the same name in the server configuration. The default value is 65536.
*/
public int maxContentLength = Connection.MAX_CONTENT_LENGTH;
/**
* The amount of time in milliseconds to wait before trying to reconnect to a dead host. The default value is
* 1000. This interval occurs after the time specified by the {@link #reconnectInitialDelay}.
*/
public int reconnectInterval = Connection.RECONNECT_INTERVAL;
/**
* The amount of time in milliseconds to wait before trying to reconnect to a dead host for the first time.
* The default value is 1000.
*/
public int reconnectInitialDelay = Connection.RECONNECT_INITIAL_DELAY;
/**
* The override value for the size of the result batches to be returned from the server. This value is set to
* 64 by default.
*/
public int resultIterationBatchSize = Connection.RESULT_ITERATION_BATCH_SIZE;
/**
* The constructor for the channel that connects to the server. This value should be the fully qualified
* class name of a Gremlin Driver {@link Channelizer} implementation. By default this value is set to
* {@link org.apache.tinkerpop.gremlin.driver.Channelizer.WebSocketChannelizer}.
*/
public String channelizer = Channelizer.WebSocketChannelizer.class.getName();
/**
* @deprecated as of 3.1.1-incubating, and not replaced as this property was never implemented internally
* as the way to establish sessions
*/
@Deprecated
public String sessionId = null;
/**
* @deprecated as of 3.1.1-incubating, and not replaced as this property was never implemented internally
* as the way to establish sessions
*/
@Deprecated
public Optional<String> optionalSessionId() {
return Optional.ofNullable(sessionId);
}
}
public static class SerializerSettings {
/**
* The fully qualified class name of the {@link MessageSerializer} that will be used to communicate with the
* server. Note that the serializer configured on the client should be supported by the server configuration.
*/
public String className = GryoMessageSerializerV1d0.class.getCanonicalName();
/**
* The configuration for the specified serializer with the {@link #className}.
*/
public Map<String, Object> config = null;
public MessageSerializer create() throws Exception {
final Class clazz = Class.forName(className);
final MessageSerializer serializer = (MessageSerializer) clazz.newInstance();
Optional.ofNullable(config).ifPresent(c -> serializer.configure(c, null));
return serializer;
}
}
}