Beispiel #1
0
        private static ClusterVNode BuildNode(ClusterNodeOptions options, Func <ClusterNodeOptions> loadConfigFunc)
        {
            var quorumSize = GetQuorumSize(options.ClusterSize);

            var disableInternalTcpTls = options.Insecure;
            var disableExternalTcpTls = options.Insecure || options.DisableExternalTcpTls;

            var httpEndPoint = new IPEndPoint(options.ExtIp, options.HttpPort);
            var intTcp       = disableInternalTcpTls ? new IPEndPoint(options.IntIp, options.IntTcpPort) : null;
            var intSecTcp    = !disableInternalTcpTls ? new IPEndPoint(options.IntIp, options.IntTcpPort) : null;
            var extTcp       = options.EnableExternalTCP && disableExternalTcpTls
                                ? new IPEndPoint(options.ExtIp, options.ExtTcpPort)
                                : null;
            var extSecTcp = options.EnableExternalTCP && !disableExternalTcpTls
                                ? new IPEndPoint(options.ExtIp, options.ExtTcpPort)
                                : null;

            var intTcpPortAdvertiseAs    = disableInternalTcpTls ? options.IntTcpPortAdvertiseAs : 0;
            var intSecTcpPortAdvertiseAs = !disableInternalTcpTls ? options.IntTcpPortAdvertiseAs : 0;
            var extTcpPortAdvertiseAs    = options.EnableExternalTCP && disableExternalTcpTls
                                ? options.ExtTcpPortAdvertiseAs
                                : 0;
            var extSecTcpPortAdvertiseAs = options.EnableExternalTCP && !disableExternalTcpTls
                                ? options.ExtTcpPortAdvertiseAs
                                : 0;

            var prepareCount = options.PrepareCount > quorumSize ? options.PrepareCount : quorumSize;
            var commitCount  = options.CommitCount > quorumSize ? options.CommitCount : quorumSize;

            Log.Information("Quorum size set to {quorum}", prepareCount);

            if (options.ReadOnlyReplica && options.ClusterSize <= 1)
            {
                throw new InvalidConfigurationException(
                          "This node cannot be configured as a Read Only Replica as these node types are only supported in a clustered configuration.");
            }

            VNodeBuilder builder;

            if (options.ClusterSize > 1)
            {
                builder = ClusterVNodeBuilder.AsClusterMember(options.ClusterSize);
                if (options.ReadOnlyReplica)
                {
                    builder.EnableReadOnlyReplica();
                }
            }
            else
            {
                builder = ClusterVNodeBuilder.AsSingleNode();
            }

            builder.WithLoadConfigFunction(loadConfigFunc);

            if (options.MemDb)
            {
                builder = builder.RunInMemory();
            }
            else
            {
                builder = builder.RunOnDisk(options.Db);
            }

            if (options.WriteStatsToDb)
            {
                builder = builder.WithStatsStorage(StatsStorage.StreamAndFile);
            }
            else
            {
                builder = builder.WithStatsStorage(StatsStorage.File);
            }

            builder.WithInternalTcpOn(intTcp)
            .WithInternalSecureTcpOn(intSecTcp)
            .WithExternalTcpOn(extTcp)
            .WithExternalSecureTcpOn(extSecTcp)
            .WithHttpOn(httpEndPoint)
            .WithWorkerThreads(options.WorkerThreads)
            .WithInternalHeartbeatTimeout(TimeSpan.FromMilliseconds(options.IntTcpHeartbeatTimeout))
            .WithInternalHeartbeatInterval(TimeSpan.FromMilliseconds(options.IntTcpHeartbeatInterval))
            .WithExternalHeartbeatTimeout(TimeSpan.FromMilliseconds(options.ExtTcpHeartbeatTimeout))
            .WithExternalHeartbeatInterval(TimeSpan.FromMilliseconds(options.ExtTcpHeartbeatInterval))
            .MaximumMemoryTableSizeOf(options.MaxMemTableSize)
            .WithHashCollisionReadLimitOf(options.HashCollisionReadLimit)
            .WithGossipInterval(TimeSpan.FromMilliseconds(options.GossipIntervalMs))
            .WithGossipAllowedTimeDifference(TimeSpan.FromMilliseconds(options.GossipAllowedDifferenceMs))
            .WithGossipTimeout(TimeSpan.FromMilliseconds(options.GossipTimeoutMs))
            .WithClusterGossipPort(options.ClusterGossipPort)
            .WithMinFlushDelay(TimeSpan.FromMilliseconds(options.MinFlushDelayMs))
            .WithPrepareTimeout(TimeSpan.FromMilliseconds(options.PrepareTimeoutMs))
            .WithCommitTimeout(TimeSpan.FromMilliseconds(options.CommitTimeoutMs))
            .WithWriteTimeout(TimeSpan.FromMilliseconds(options.WriteTimeoutMs))
            .WithStatsPeriod(TimeSpan.FromSeconds(options.StatsPeriodSec))
            .WithDeadMemberRemovalPeriod(TimeSpan.FromSeconds(options.DeadMemberRemovalPeriodSec))
            .WithPrepareCount(prepareCount)
            .WithCommitCount(commitCount)
            .WithNodePriority(options.NodePriority)
            .WithScavengeHistoryMaxAge(options.ScavengeHistoryMaxAge)
            .WithIndexPath(options.Index)
            .WithIndexVerification(options.SkipIndexVerify)
            .WithIndexCacheDepth(options.IndexCacheDepth)
            .WithIndexMergeOptimization(options.OptimizeIndexMerge)
            .RunProjections(options.RunProjections, options.ProjectionThreads, options.FaultOutOfOrderProjections)
            .WithProjectionQueryExpirationOf(TimeSpan.FromMinutes(options.ProjectionsQueryExpiry))
            .WithTfCachedChunks(options.CachedChunks)
            .WithTfChunksCacheSize(options.ChunksCacheSize)
            .AdvertiseInternalHostAs(options.IntHostAdvertiseAs)
            .AdvertiseExternalHostAs(options.ExtHostAdvertiseAs)
            .AdvertiseHostToClientAs(options.AdvertiseHostToClientAs)
            .AdvertiseHttpPortToClientAs(options.AdvertiseHttpPortToClientAs)
            .AdvertiseTcpPortToClientAs(options.AdvertiseTcpPortToClientAs)
            .AdvertiseHttpPortAs(options.HttpPortAdvertiseAs)
            .AdvertiseInternalTCPPortAs(intTcpPortAdvertiseAs)
            .AdvertiseExternalTCPPortAs(extTcpPortAdvertiseAs)
            .AdvertiseInternalSecureTCPPortAs(intSecTcpPortAdvertiseAs)
            .AdvertiseExternalSecureTCPPortAs(extSecTcpPortAdvertiseAs)
            .HavingReaderThreads(options.ReaderThreadsCount)
            .WithConnectionPendingSendBytesThreshold(options.ConnectionPendingSendBytesThreshold)
            .WithConnectionQueueSizeThreshold(options.ConnectionQueueSizeThreshold)
            .WithChunkInitialReaderCount(options.ChunkInitialReaderCount)
            .WithInitializationThreads(options.InitializationThreads)
            .WithMaxAutoMergeIndexLevel(options.MaxAutoMergeIndexLevel)
            .WithMaxTruncation(options.MaxTruncation)
            .WithMaxAppendSize(options.MaxAppendSize)
            .WithEnableAtomPubOverHTTP(options.EnableAtomPubOverHTTP)
            .WithStreamInfoCacheCapacity(options.StreamInfoCacheCapacity);

            if (options.GossipSeed.Length > 0)
            {
                builder.WithGossipSeeds(options.GossipSeed);
            }

            if (options.DiscoverViaDns)
            {
                builder.WithClusterDnsName(options.ClusterDns);
            }
            else
            {
                builder.DisableDnsDiscovery();
            }

            if (options.GossipOnSingleNode)
            {
                builder.GossipAsSingleNode();
            }

            if (options.EnableTrustedAuth)
            {
                builder.EnableTrustedAuth();
            }
            if (options.StartStandardProjections)
            {
                builder.StartStandardProjections();
            }
            if (options.DisableHTTPCaching)
            {
                builder.DisableHTTPCaching();
            }
            if (options.DisableScavengeMerging)
            {
                builder.DisableScavengeMerging();
            }
            if (options.LogHttpRequests)
            {
                builder.EnableLoggingOfHttpRequests();
            }
            if (options.LogFailedAuthenticationAttempts)
            {
                builder.EnableLoggingOfFailedAuthenticationAttempts();
            }
            if (options.EnableHistograms)
            {
                builder.EnableHistograms();
            }
            if (options.UnsafeIgnoreHardDelete)
            {
                builder.WithUnsafeIgnoreHardDelete();
            }
            if (options.UnsafeDisableFlushToDisk)
            {
                builder.WithUnsafeDisableFlushToDisk();
            }
            if (options.Insecure)
            {
                if (options.DisableInternalTcpTls || options.DisableExternalTcpTls)
                {
                    throw new InvalidConfigurationException($"The '{nameof(options.Insecure)}' option cannot be combined with the '{nameof(options.DisableInternalTcpTls)}' or the '{nameof(options.DisableExternalTcpTls)}' options.");
                }

                builder.DisableInternalTcpTls();
                builder.DisableExternalTcpTls();
                builder.DisableHttps();
            }
            if (options.DisableExternalTcpTls)
            {
                builder.DisableExternalTcpTls();
            }
            if (options.EnableExternalTCP)
            {
                builder.EnableExternalTCP();
            }
            if (options.DisableAdminUi)
            {
                builder.NoAdminOnPublicInterface();
            }
            if (options.DisableStatsOnHttp)
            {
                builder.NoStatsOnPublicInterface();
            }
            if (options.DisableGossipOnHttp)
            {
                builder.NoGossipOnPublicInterface();
            }
            if (options.SkipDbVerify)
            {
                builder.DoNotVerifyDbHashes();
            }
            if (options.AlwaysKeepScavenged)
            {
                builder.AlwaysKeepScavenged();
            }
            if (options.Unbuffered)
            {
                builder.EnableUnbuffered();
            }
            if (options.WriteThrough)
            {
                builder.EnableWriteThrough();
            }
            if (options.SkipIndexScanOnReads)
            {
                builder.SkipIndexScanOnReads();
            }
            if (options.ReduceFileCachePressure)
            {
                builder.ReduceFileCachePressure();
            }
            if (options.DisableFirstLevelHttpAuthorization)
            {
                builder.DisableFirstLevelHttpAuthorization();
            }
            if (options.UnsafeAllowSurplusNodes)
            {
                builder.WithUnsafeAllowSurplusNodes();
            }

            builder.WithCertificateReservedNodeCommonName(options.CertificateReservedNodeCommonName);

            bool requireCertificates = !options.Insecure;

            if (options.Insecure)
            {
                Log.Warning(
                    "Authentication and Authorization is disabled on all TCP/HTTP interfaces. " +
                    "It is recommended to run with Authentication and Authorization enabled in production");
                Log.Warning(
                    "TLS is disabled on all TCP/HTTP interfaces - no certificates are required to run EventStoreDB. " +
                    "It is recommended to run with TLS enabled in production.");
            }
            else
            {
                Log.Information(
                    "TLS is enabled on at least one TCP/HTTP interface - a certificate is required to run EventStoreDB.");
            }

            if (requireCertificates)
            {
                if (!string.IsNullOrWhiteSpace(options.CertificateStoreLocation))
                {
                    var location = CertificateLoader.GetCertificateStoreLocation(options.CertificateStoreLocation);
                    var name     = CertificateLoader.GetCertificateStoreName(options.CertificateStoreName);
                    builder.WithServerCertificateFromStore(location, name, options.CertificateSubjectName,
                                                           options.CertificateThumbprint);
                }
                else if (!string.IsNullOrWhiteSpace(options.CertificateStoreName))
                {
                    var name = CertificateLoader.GetCertificateStoreName(options.CertificateStoreName);
                    builder.WithServerCertificateFromStore(name, options.CertificateSubjectName,
                                                           options.CertificateThumbprint);
                }
                else if (options.CertificateFile.IsNotEmptyString())
                {
                    builder.WithServerCertificateFromFile(
                        options.CertificateFile,
                        options.CertificatePrivateKeyFile,
                        options.CertificatePassword);
                }
                else
                {
                    throw new InvalidConfigurationException(
                              "A certificate is required unless insecure mode (--insecure) is set.");
                }

                if (!string.IsNullOrEmpty(options.TrustedRootCertificatesPath))
                {
                    builder.WithTrustedRootCertificatesPath(options.TrustedRootCertificatesPath);
                }
                else
                {
                    throw new InvalidConfigurationException(
                              $"{nameof(options.TrustedRootCertificatesPath)} must be specified unless insecure mode (--insecure) is set.");
                }
            }

            var authorizationConfig = String.IsNullOrEmpty(options.AuthorizationConfig)
                                ? options.Config
                                : options.AuthorizationConfig;

            var authenticationConfig = String.IsNullOrEmpty(options.AuthenticationConfig)
                                ? options.Config
                                : options.AuthenticationConfig;

            var pluginLoader = new PluginLoader(new DirectoryInfo(Locations.PluginsDirectory));

            AuthenticationProviderFactory authenticationProviderFactory;
            AuthorizationProviderFactory  authorizationProviderFactory;

            if (!options.Insecure)
            {
                authorizationProviderFactory =
                    GetAuthorizationProviderFactory(options.AuthorizationType, authorizationConfig, pluginLoader);
                authenticationProviderFactory =
                    GetAuthenticationProviderFactory(options.AuthenticationType, authenticationConfig, pluginLoader);
            }
            else
            {
                authorizationProviderFactory  = new AuthorizationProviderFactory(components => new PassthroughAuthorizationProviderFactory());
                authenticationProviderFactory = new AuthenticationProviderFactory(components => new PassthroughAuthenticationProviderFactory());
            }

            var plugInContainer = FindPlugins();

            var consumerStrategyFactories = GetPlugInConsumerStrategyFactories(plugInContainer);

            builder.WithAuthenticationProviderFactory(authenticationProviderFactory,
                                                      options.AuthenticationType == Opts.AuthenticationTypeDefault && !options.Insecure);
            builder.WithAuthorizationProvider(authorizationProviderFactory);
            var subsystemFactories = GetPlugInSubsystemFactories(plugInContainer);

            foreach (var subsystemFactory in subsystemFactories)
            {
                var subsystem = subsystemFactory.Create(options.Config);
                builder.AddCustomSubsystem(subsystem);
            }

            return(builder.Build(options, consumerStrategyFactories));
        }
Beispiel #2
0
        private static ClusterVNode BuildNode(ClusterNodeOptions options)
        {
            var quorumSize = GetQuorumSize(options.ClusterSize);

            var intHttp   = new IPEndPoint(options.IntIp, options.IntHttpPort);
            var extHttp   = new IPEndPoint(options.ExtIp, options.ExtHttpPort);
            var intTcp    = new IPEndPoint(options.IntIp, options.IntTcpPort);
            var intSecTcp = options.IntSecureTcpPort > 0 ? new IPEndPoint(options.IntIp, options.IntSecureTcpPort) : null;
            var extTcp    = new IPEndPoint(options.ExtIp, options.ExtTcpPort);
            var extSecTcp = options.ExtSecureTcpPort > 0 ? new IPEndPoint(options.ExtIp, options.ExtSecureTcpPort) : null;

            var prepareCount = options.PrepareCount > quorumSize ? options.PrepareCount : quorumSize;
            var commitCount  = options.CommitCount > quorumSize ? options.CommitCount : quorumSize;

            Log.Info("Quorum size set to " + prepareCount);
            if (options.DisableInsecureTCP)
            {
                if (!options.UseInternalSsl)
                {
                    throw new Exception("You have chosen to disable the insecure TCP ports and haven't set 'UseInternalSsl'. The nodes in the cluster will not be able to communicate properly.");
                }
                if (extSecTcp == null || intSecTcp == null)
                {
                    throw new Exception("You have chosen to disable the insecure TCP ports and haven't setup the External or Internal Secure TCP Ports.");
                }
            }
            if (options.UseInternalSsl)
            {
                if (ReferenceEquals(options.SslTargetHost, Opts.SslTargetHostDefault))
                {
                    throw new Exception("No SSL target host specified.");
                }
                if (intSecTcp == null)
                {
                    throw new Exception("Usage of internal secure communication is specified, but no internal secure endpoint is specified!");
                }
            }

            VNodeBuilder builder;

            if (options.ClusterSize > 1)
            {
                builder = ClusterVNodeBuilder.AsClusterMember(options.ClusterSize);
            }
            else
            {
                builder = ClusterVNodeBuilder.AsSingleNode();
            }
            if (options.MemDb)
            {
                builder = builder.RunInMemory();
            }
            else
            {
                builder = builder.RunOnDisk(options.Db);
            }

            builder.WithInternalTcpOn(intTcp)
            .WithInternalSecureTcpOn(intSecTcp)
            .WithExternalTcpOn(extTcp)
            .WithExternalSecureTcpOn(extSecTcp)
            .WithInternalHttpOn(intHttp)
            .WithExternalHttpOn(extHttp)
            .WithWorkerThreads(options.WorkerThreads)
            .WithInternalHeartbeatTimeout(TimeSpan.FromMilliseconds(options.IntTcpHeartbeatTimeout))
            .WithInternalHeartbeatInterval(TimeSpan.FromMilliseconds(options.IntTcpHeartbeatInterval))
            .WithExternalHeartbeatTimeout(TimeSpan.FromMilliseconds(options.ExtTcpHeartbeatTimeout))
            .WithExternalHeartbeatInterval(TimeSpan.FromMilliseconds(options.ExtTcpHeartbeatInterval))
            .MaximumMemoryTableSizeOf(options.MaxMemTableSize)
            .WithHashCollisionReadLimitOf(options.HashCollisionReadLimit)
            .WithGossipInterval(TimeSpan.FromMilliseconds(options.GossipIntervalMs))
            .WithGossipAllowedTimeDifference(TimeSpan.FromMilliseconds(options.GossipAllowedDifferenceMs))
            .WithGossipTimeout(TimeSpan.FromMilliseconds(options.GossipTimeoutMs))
            .WithClusterGossipPort(options.ClusterGossipPort)
            .WithMinFlushDelay(TimeSpan.FromMilliseconds(options.MinFlushDelayMs))
            .WithPrepareTimeout(TimeSpan.FromMilliseconds(options.PrepareTimeoutMs))
            .WithCommitTimeout(TimeSpan.FromMilliseconds(options.CommitTimeoutMs))
            .WithStatsPeriod(TimeSpan.FromSeconds(options.StatsPeriodSec))
            .WithPrepareCount(prepareCount)
            .WithCommitCount(commitCount)
            .WithNodePriority(options.NodePriority)
            .WithScavengeHistoryMaxAge(options.ScavengeHistoryMaxAge)
            .WithIndexPath(options.Index)
            .WithIndexCacheDepth(options.IndexCacheDepth)
            .WithSslTargetHost(options.SslTargetHost)
            .RunProjections(options.RunProjections, options.ProjectionThreads)
            .WithTfCachedChunks(options.CachedChunks)
            .WithTfChunksCacheSize(options.ChunksCacheSize)
            .WithStatsStorage(StatsStorage.StreamAndCsv)
            .AdvertiseInternalIPAs(options.IntIpAdvertiseAs)
            .AdvertiseExternalIPAs(options.ExtIpAdvertiseAs)
            .AdvertiseInternalHttpPortAs(options.IntHttpPortAdvertiseAs)
            .AdvertiseExternalHttpPortAs(options.ExtHttpPortAdvertiseAs)
            .AdvertiseInternalTCPPortAs(options.IntTcpPortAdvertiseAs)
            .AdvertiseExternalTCPPortAs(options.ExtTcpPortAdvertiseAs)
            .AdvertiseInternalSecureTCPPortAs(options.IntSecureTcpPortAdvertiseAs)
            .AdvertiseExternalSecureTCPPortAs(options.ExtSecureTcpPortAdvertiseAs)
            .HavingReaderThreads(options.ReaderThreadsCount);

            if (options.GossipSeed.Length > 0)
            {
                builder.WithGossipSeeds(options.GossipSeed);
            }

            if (options.DiscoverViaDns)
            {
                builder.WithClusterDnsName(options.ClusterDns);
            }
            else
            {
                builder.DisableDnsDiscovery();
            }

            if (!options.AddInterfacePrefixes)
            {
                builder.DontAddInterfacePrefixes();
            }
            if (options.GossipOnSingleNode)
            {
                builder.GossipAsSingleNode();
            }
            foreach (var prefix in options.IntHttpPrefixes)
            {
                builder.AddInternalHttpPrefix(prefix);
            }
            foreach (var prefix in options.ExtHttpPrefixes)
            {
                builder.AddExternalHttpPrefix(prefix);
            }

            if (options.EnableTrustedAuth)
            {
                builder.EnableTrustedAuth();
            }
            if (options.StartStandardProjections)
            {
                builder.StartStandardProjections();
            }
            if (options.DisableHTTPCaching)
            {
                builder.DisableHTTPCaching();
            }
            if (options.DisableScavengeMerging)
            {
                builder.DisableScavengeMerging();
            }
            if (options.LogHttpRequests)
            {
                builder.EnableLoggingOfHttpRequests();
            }
            if (options.EnableHistograms)
            {
                builder.EnableHistograms();
            }
            if (options.UnsafeIgnoreHardDelete)
            {
                builder.WithUnsafeIgnoreHardDelete();
            }
            if (options.UnsafeDisableFlushToDisk)
            {
                builder.WithUnsafeDisableFlushToDisk();
            }
            if (options.BetterOrdering)
            {
                builder.WithBetterOrdering();
            }
            if (options.SslValidateServer)
            {
                builder.ValidateSslServer();
            }
            if (options.UseInternalSsl)
            {
                builder.EnableSsl();
            }
            if (options.DisableInsecureTCP)
            {
                builder.DisableInsecureTCP();
            }
            if (!options.AdminOnExt)
            {
                builder.NoAdminOnPublicInterface();
            }
            if (!options.StatsOnExt)
            {
                builder.NoStatsOnPublicInterface();
            }
            if (!options.GossipOnExt)
            {
                builder.NoGossipOnPublicInterface();
            }
            if (options.SkipDbVerify)
            {
                builder.DoNotVerifyDbHashes();
            }
            if (options.AlwaysKeepScavenged)
            {
                builder.AlwaysKeepScavenged();
            }
            if (options.Unbuffered)
            {
                builder.EnableUnbuffered();
            }
            if (options.WriteThrough)
            {
                builder.EnableWriteThrough();
            }

            if (options.IntSecureTcpPort > 0 || options.ExtSecureTcpPort > 0)
            {
                if (!string.IsNullOrWhiteSpace(options.CertificateStoreLocation))
                {
                    var location = GetCertificateStoreLocation(options.CertificateStoreLocation);
                    var name     = GetCertificateStoreName(options.CertificateStoreName);
                    builder.WithServerCertificateFromStore(location, name, options.CertificateSubjectName, options.CertificateThumbprint);
                }
                else if (!string.IsNullOrWhiteSpace(options.CertificateStoreName))
                {
                    var name = GetCertificateStoreName(options.CertificateStoreName);
                    builder.WithServerCertificateFromStore(name, options.CertificateSubjectName, options.CertificateThumbprint);
                }
                else if (options.CertificateFile.IsNotEmptyString())
                {
                    builder.WithServerCertificateFromFile(options.CertificateFile, options.CertificatePassword);
                }
                else
                {
                    throw new Exception("No server certificate specified.");
                }
            }

            var authenticationConfig          = String.IsNullOrEmpty(options.AuthenticationConfig) ? options.Config : options.AuthenticationConfig;
            var plugInContainer               = FindPlugins();
            var authenticationProviderFactory = GetAuthenticationProviderFactory(options.AuthenticationType, authenticationConfig, plugInContainer);
            var consumerStrategyFactories     = GetPlugInConsumerStrategyFactories(plugInContainer);

            builder.WithAuthenticationProvider(authenticationProviderFactory);

            return(builder.Build(options, consumerStrategyFactories));
        }
Beispiel #3
0
        private static ClusterVNode BuildNode(ClusterNodeOptions options)
        {
            var quorumSize = GetQuorumSize(options.ClusterSize);

            var intHttp   = new IPEndPoint(options.IntIp, options.IntHttpPort);
            var extHttp   = new IPEndPoint(options.ExtIp, options.ExtHttpPort);
            var intTcp    = new IPEndPoint(options.IntIp, options.IntTcpPort);
            var intSecTcp = options.IntSecureTcpPort > 0
                                ? new IPEndPoint(options.IntIp, options.IntSecureTcpPort)
                                : null;
            var extTcp    = new IPEndPoint(options.ExtIp, options.ExtTcpPort);
            var extSecTcp = options.ExtSecureTcpPort > 0
                                ? new IPEndPoint(options.ExtIp, options.ExtSecureTcpPort)
                                : null;

            var prepareCount = options.PrepareCount > quorumSize ? options.PrepareCount : quorumSize;
            var commitCount  = options.CommitCount > quorumSize ? options.CommitCount : quorumSize;

            Log.Info("Quorum size set to {quorum}", prepareCount);
            if (options.DisableInsecureTCP)
            {
                if (!options.UseInternalSsl)
                {
                    throw new Exception(
                              "You have chosen to disable the insecure TCP ports and haven't set 'UseInternalSsl'. The nodes in the cluster will not be able to communicate properly.");
                }

                if (extSecTcp == null || intSecTcp == null)
                {
                    throw new Exception(
                              "You have chosen to disable the insecure TCP ports and haven't setup the External or Internal Secure TCP Ports.");
                }
            }

            if (options.UseInternalSsl)
            {
                if (ReferenceEquals(options.SslTargetHost, Opts.SslTargetHostDefault))
                {
                    throw new Exception("No SSL target host specified.");
                }
                if (intSecTcp == null)
                {
                    throw new Exception(
                              "Usage of internal secure communication is specified, but no internal secure endpoint is specified!");
                }
            }

            if (options.ReadOnlyReplica && options.ClusterSize <= 1)
            {
                throw new Exception(
                          "This node cannot be configured as a Read Only Replica as these node types are only supported in a clustered configuration.");
            }

            VNodeBuilder builder;

            if (options.ClusterSize > 1)
            {
                builder = ClusterVNodeBuilder.AsClusterMember(options.ClusterSize);
                if (options.ReadOnlyReplica)
                {
                    builder.EnableReadOnlyReplica();
                }
            }
            else
            {
                builder = ClusterVNodeBuilder.AsSingleNode();
            }

            if (options.MemDb)
            {
                builder = builder.RunInMemory();
            }
            else
            {
                builder = builder.RunOnDisk(options.Db);
            }

            if (options.WriteStatsToDb)
            {
                builder = builder.WithStatsStorage(StatsStorage.StreamAndFile);
            }
            else
            {
                builder = builder.WithStatsStorage(StatsStorage.File);
            }

            builder.WithInternalTcpOn(intTcp)
            .WithInternalSecureTcpOn(intSecTcp)
            .WithExternalTcpOn(extTcp)
            .WithExternalSecureTcpOn(extSecTcp)
            .WithInternalHttpOn(intHttp)
            .WithExternalHttpOn(extHttp)
            .WithWorkerThreads(options.WorkerThreads)
            .WithInternalHeartbeatTimeout(TimeSpan.FromMilliseconds(options.IntTcpHeartbeatTimeout))
            .WithInternalHeartbeatInterval(TimeSpan.FromMilliseconds(options.IntTcpHeartbeatInterval))
            .WithExternalHeartbeatTimeout(TimeSpan.FromMilliseconds(options.ExtTcpHeartbeatTimeout))
            .WithExternalHeartbeatInterval(TimeSpan.FromMilliseconds(options.ExtTcpHeartbeatInterval))
            .MaximumMemoryTableSizeOf(options.MaxMemTableSize)
            .WithHashCollisionReadLimitOf(options.HashCollisionReadLimit)
            .WithGossipInterval(TimeSpan.FromMilliseconds(options.GossipIntervalMs))
            .WithGossipAllowedTimeDifference(TimeSpan.FromMilliseconds(options.GossipAllowedDifferenceMs))
            .WithGossipTimeout(TimeSpan.FromMilliseconds(options.GossipTimeoutMs))
            .WithClusterGossipPort(options.ClusterGossipPort)
            .WithMinFlushDelay(TimeSpan.FromMilliseconds(options.MinFlushDelayMs))
            .WithPrepareTimeout(TimeSpan.FromMilliseconds(options.PrepareTimeoutMs))
            .WithCommitTimeout(TimeSpan.FromMilliseconds(options.CommitTimeoutMs))
            .WithStatsPeriod(TimeSpan.FromSeconds(options.StatsPeriodSec))
            .WithPrepareCount(prepareCount)
            .WithCommitCount(commitCount)
            .WithNodePriority(options.NodePriority)
            .WithScavengeHistoryMaxAge(options.ScavengeHistoryMaxAge)
            .WithIndexPath(options.Index)
            .WithIndexVerification(options.SkipIndexVerify)
            .WithIndexCacheDepth(options.IndexCacheDepth)
            .WithIndexMergeOptimization(options.OptimizeIndexMerge)
            .WithSslTargetHost(options.SslTargetHost)
            .RunProjections(options.RunProjections, options.ProjectionThreads, options.FaultOutOfOrderProjections)
            .WithProjectionQueryExpirationOf(TimeSpan.FromMinutes(options.ProjectionsQueryExpiry))
            .WithTfCachedChunks(options.CachedChunks)
            .WithTfChunksCacheSize(options.ChunksCacheSize)
            .AdvertiseInternalIPAs(options.IntIpAdvertiseAs)
            .AdvertiseExternalIPAs(options.ExtIpAdvertiseAs)
            .AdvertiseInternalHttpPortAs(options.IntHttpPortAdvertiseAs)
            .AdvertiseExternalHttpPortAs(options.ExtHttpPortAdvertiseAs)
            .AdvertiseInternalTCPPortAs(options.IntTcpPortAdvertiseAs)
            .AdvertiseExternalTCPPortAs(options.ExtTcpPortAdvertiseAs)
            .AdvertiseInternalSecureTCPPortAs(options.IntSecureTcpPortAdvertiseAs)
            .AdvertiseExternalSecureTCPPortAs(options.ExtSecureTcpPortAdvertiseAs)
            .HavingReaderThreads(options.ReaderThreadsCount)
            .WithConnectionPendingSendBytesThreshold(options.ConnectionPendingSendBytesThreshold)
            .WithConnectionQueueSizeThreshold(options.ConnectionQueueSizeThreshold)
            .WithChunkInitialReaderCount(options.ChunkInitialReaderCount)
            .WithInitializationThreads(options.InitializationThreads)
            .WithMaxAutoMergeIndexLevel(options.MaxAutoMergeIndexLevel)
            .WithMaxAppendSize(options.MaxAppendSize);

            if (options.GossipSeed.Length > 0)
            {
                builder.WithGossipSeeds(options.GossipSeed);
            }

            if (options.DiscoverViaDns)
            {
                builder.WithClusterDnsName(options.ClusterDns);
            }
            else
            {
                builder.DisableDnsDiscovery();
            }

            if (options.GossipOnSingleNode)
            {
                builder.GossipAsSingleNode();
            }

            if (options.EnableTrustedAuth)
            {
                builder.EnableTrustedAuth();
            }
            if (options.StartStandardProjections)
            {
                builder.StartStandardProjections();
            }
            if (options.DisableHTTPCaching)
            {
                builder.DisableHTTPCaching();
            }
            if (options.DisableScavengeMerging)
            {
                builder.DisableScavengeMerging();
            }
            if (options.LogHttpRequests)
            {
                builder.EnableLoggingOfHttpRequests();
            }
            if (options.LogFailedAuthenticationAttempts)
            {
                builder.EnableLoggingOfFailedAuthenticationAttempts();
            }
            if (options.EnableHistograms)
            {
                builder.EnableHistograms();
            }
            if (options.UnsafeIgnoreHardDelete)
            {
                builder.WithUnsafeIgnoreHardDelete();
            }
            if (options.UnsafeDisableFlushToDisk)
            {
                builder.WithUnsafeDisableFlushToDisk();
            }
            if (options.BetterOrdering)
            {
                builder.WithBetterOrdering();
            }
            if (options.SslValidateServer)
            {
                builder.ValidateSslServer();
            }
            if (options.UseInternalSsl)
            {
                builder.EnableSsl();
            }
            if (options.DisableInsecureTCP)
            {
                builder.DisableInsecureTCP();
            }
            if (!options.AdminOnExt)
            {
                builder.NoAdminOnPublicInterface();
            }
            if (!options.StatsOnExt)
            {
                builder.NoStatsOnPublicInterface();
            }
            if (!options.GossipOnExt)
            {
                builder.NoGossipOnPublicInterface();
            }
            if (options.SkipDbVerify)
            {
                builder.DoNotVerifyDbHashes();
            }
            if (options.AlwaysKeepScavenged)
            {
                builder.AlwaysKeepScavenged();
            }
            if (options.Unbuffered)
            {
                builder.EnableUnbuffered();
            }
            if (options.WriteThrough)
            {
                builder.EnableWriteThrough();
            }
            if (options.SkipIndexScanOnReads)
            {
                builder.SkipIndexScanOnReads();
            }
            if (options.ReduceFileCachePressure)
            {
                builder.ReduceFileCachePressure();
            }
            if (options.StructuredLog)
            {
                builder.WithStructuredLogging(options.StructuredLog);
            }
            if (options.DisableFirstLevelHttpAuthorization)
            {
                builder.DisableFirstLevelHttpAuthorization();
            }

            if (!string.IsNullOrWhiteSpace(options.CertificateStoreLocation))
            {
                var location = GetCertificateStoreLocation(options.CertificateStoreLocation);
                var name     = GetCertificateStoreName(options.CertificateStoreName);
                builder.WithServerCertificateFromStore(location, name, options.CertificateSubjectName,
                                                       options.CertificateThumbprint);
            }
            else if (!string.IsNullOrWhiteSpace(options.CertificateStoreName))
            {
                var name = GetCertificateStoreName(options.CertificateStoreName);
                builder.WithServerCertificateFromStore(name, options.CertificateSubjectName,
                                                       options.CertificateThumbprint);
            }
            else if (options.CertificateFile.IsNotEmptyString())
            {
                builder.WithServerCertificateFromFile(options.CertificateFile, options.CertificatePassword);
            }
            else if (!options.Dev)
            {
                throw new Exception("An SSL Certificate is required unless development mode (--dev) is set.");
            }

            var authenticationConfig = String.IsNullOrEmpty(options.AuthenticationConfig)
                                ? options.Config
                                : options.AuthenticationConfig;
            var plugInContainer = FindPlugins();
            var authenticationProviderFactory =
                GetAuthenticationProviderFactory(options.AuthenticationType, authenticationConfig, plugInContainer);
            var consumerStrategyFactories = GetPlugInConsumerStrategyFactories(plugInContainer);

            builder.WithAuthenticationProvider(authenticationProviderFactory);
            var subsystemFactories = GetPlugInSubsystemFactories(plugInContainer);

            foreach (var subsystemFactory in subsystemFactories)
            {
                var subsystem = subsystemFactory.Create(options.Config);
                builder.AddCustomSubsystem(subsystem);
            }

            return(builder.Build(options, consumerStrategyFactories));
        }
        /// <summary>
        /// Returns a builder set to construct options for a cluster node instance with a cluster size.
        /// </summary>
        /// <returns>A <see cref="VNodeBuilder"/> with the options set.</returns>
        public static ClusterVNodeBuilder AsClusterMember(int clusterSize)
        {
            var ret = new ClusterVNodeBuilder().WithClusterNodeSettings(clusterSize);

            return((ClusterVNodeBuilder)ret);
        }
        /// <summary>
        /// Returns a builder set to construct options for a single node instance.
        /// </summary>
        /// <returns>A <see cref="VNodeBuilder"/> with the options set.</returns>
        public static ClusterVNodeBuilder AsSingleNode()
        {
            var ret = new ClusterVNodeBuilder().WithSingleNodeSettings();

            return((ClusterVNodeBuilder)ret);
        }
 /// <summary>
 /// Returns a builder set to construct options for a cluster node instance with a cluster size 
 /// </summary>
 /// <returns>A <see cref="VNodeBuilder"/> with the options set</returns>
 public static ClusterVNodeBuilder AsClusterMember(int clusterSize)
 {
     var ret = new ClusterVNodeBuilder().WithClusterNodeSettings(clusterSize);
     return (ClusterVNodeBuilder)ret;
 }
 /// <summary>
 /// Returns a builder set to construct options for a single node instance
 /// </summary>
 /// <returns>A <see cref="VNodeBuilder"/> with the options set</returns>
 public static ClusterVNodeBuilder AsSingleNode()
 {
     var ret = new ClusterVNodeBuilder().WithSingleNodeSettings();
     return (ClusterVNodeBuilder)ret;
 }