예제 #1
0
        public void Flush()
        {
            var last = Interlocked.Read(ref _last);

            if (last == _lastFlushed)
            {
                return;
            }

            _accessor.Write(0, last);
            _accessor.Flush();

            //FlushViewOfFile(_accessor.SafeMemoryMappedViewHandle.DangerousGetHandle(), (UIntPtr)sizeof(long));
            if (!FileStreamExtensions.FlushFileBuffers(_fileHandle))
            {
                throw new Exception(string.Format("FlushFileBuffers failed with err: {0}", Marshal.GetLastWin32Error()));
            }

            Interlocked.Exchange(ref _lastFlushed, last);

            lock (_flushLocker)
            {
                Monitor.PulseAll(_flushLocker);
            }
        }
예제 #2
0
        public MiniClusterNode(
            string pathname, int debugIndex, IPEndPoint internalTcp, IPEndPoint internalTcpSec, IPEndPoint internalHttp,
            IPEndPoint externalTcp, IPEndPoint externalTcpSec, IPEndPoint externalHttp, IPEndPoint[] gossipSeeds,
            ISubsystem[] subsystems = null, int?chunkSize = null, int?cachedChunkSize = null,
            bool enableTrustedAuth  = false, bool skipInitializeStandardUsersCheck = true, int memTableSize = 1000,
            bool inMemDb            = true, bool disableFlushToDisk = false)
        {
            RunningTime.Start();
            RunCount += 1;

            _dbPath = Path.Combine(
                pathname,
                string.Format(
                    "mini-cluster-node-db-{0}-{1}-{2}", externalTcp.Port, externalTcpSec.Port, externalHttp.Port));

            Directory.CreateDirectory(_dbPath);
            FileStreamExtensions.ConfigureFlush(disableFlushToDisk);
            Db =
                new TFChunkDb(
                    CreateDbConfig(chunkSize ?? ChunkSize, _dbPath, cachedChunkSize ?? CachedChunkSize, inMemDb));

            InternalTcpEndPoint    = internalTcp;
            InternalTcpSecEndPoint = internalTcpSec;
            InternalHttpEndPoint   = internalHttp;

            ExternalTcpEndPoint    = externalTcp;
            ExternalTcpSecEndPoint = externalTcpSec;
            ExternalHttpEndPoint   = externalHttp;

            var singleVNodeSettings = new ClusterVNodeSettings(
                Guid.NewGuid(), debugIndex, InternalTcpEndPoint, InternalTcpSecEndPoint, ExternalTcpEndPoint,
                ExternalTcpSecEndPoint, InternalHttpEndPoint, ExternalHttpEndPoint,
                new Data.GossipAdvertiseInfo(InternalTcpEndPoint, InternalTcpSecEndPoint,
                                             ExternalTcpEndPoint, ExternalTcpSecEndPoint,
                                             InternalHttpEndPoint, ExternalHttpEndPoint),
                new[] { InternalHttpEndPoint.ToHttpUrl() }, new[] { ExternalHttpEndPoint.ToHttpUrl() }, enableTrustedAuth, ssl_connections.GetCertificate(), 1, false,
                "", gossipSeeds, TFConsts.MinFlushDelayMs, 3, 2, 2, TimeSpan.FromSeconds(2), TimeSpan.FromSeconds(2),
                false, "", false, TimeSpan.FromHours(1), StatsStorage.None, 0,
                new InternalAuthenticationProviderFactory(), disableScavengeMerging: true, scavengeHistoryMaxAge: 30, adminOnPublic: true,
                statsOnPublic: true, gossipOnPublic: true, gossipInterval: TimeSpan.FromSeconds(1),
                gossipAllowedTimeDifference: TimeSpan.FromSeconds(1), gossipTimeout: TimeSpan.FromSeconds(1),
                extTcpHeartbeatTimeout: TimeSpan.FromSeconds(10), extTcpHeartbeatInterval: TimeSpan.FromSeconds(10),
                intTcpHeartbeatTimeout: TimeSpan.FromSeconds(10), intTcpHeartbeatInterval: TimeSpan.FromSeconds(10),
                verifyDbHash: false, maxMemtableEntryCount: memTableSize, startStandardProjections: false, disableHTTPCaching: false, logHttpRequests: false);

            Log.Info(
                "\n{0,-25} {1} ({2}/{3}, {4})\n" + "{5,-25} {6} ({7})\n" + "{8,-25} {9} ({10}-bit)\n"
                + "{11,-25} {12}\n" + "{13,-25} {14}\n" + "{15,-25} {16}\n" + "{17,-25} {18}\n" + "{19,-25} {20}\n\n",
                "ES VERSION:", VersionInfo.Version, VersionInfo.Branch, VersionInfo.Hashtag, VersionInfo.Timestamp,
                "OS:", OS.OsFlavor, Environment.OSVersion, "RUNTIME:", OS.GetRuntimeVersion(),
                Marshal.SizeOf(typeof(IntPtr)) * 8, "GC:",
                GC.MaxGeneration == 0
                    ? "NON-GENERATION (PROBABLY BOEHM)"
                    : string.Format("{0} GENERATIONS", GC.MaxGeneration + 1), "DBPATH:", _dbPath, "ExTCP ENDPOINT:",
                ExternalTcpEndPoint, "ExTCP SECURE ENDPOINT:", ExternalTcpSecEndPoint, "ExHTTP ENDPOINT:",
                ExternalHttpEndPoint);

            Node = new ClusterVNode(Db, singleVNodeSettings, infoController: new InfoController(null, ProjectionType.None), subsystems: subsystems, gossipSeedSource: new KnownEndpointGossipSeedSource(gossipSeeds));
            Node.ExternalHttpService.SetupController(new TestController(Node.MainQueue));
        }
예제 #3
0
        protected override void Create(SingleNodeOptions opts)
        {
            var dbPath = Path.GetFullPath(ResolveDbPath(opts.DbPath, opts.HttpPort));

            if (!opts.InMemDb)
            {
                _dbLock = new ExclusiveDbLock(dbPath);
                if (!_dbLock.Acquire())
                {
                    throw new Exception(string.Format("Couldn't acquire exclusive lock on DB at '{0}'.", dbPath));
                }
            }

            FileStreamExtensions.ConfigureFlush(disableFlushToDisk: opts.UnsafeDisableFlushToDisk);
            var db             = new TFChunkDb(CreateDbConfig(dbPath, opts.CachedChunks, opts.ChunksCacheSize, opts.InMemDb));
            var vnodeSettings  = GetVNodeSettings(opts);
            var dbVerifyHashes = !opts.SkipDbVerify;
            var runProjections = opts.RunProjections;

            Log.Info("\n{0,-25} {1}\n{2,-25} {3} (0x{3:X})\n{4,-25} {5} (0x{5:X})\n{6,-25} {7} (0x{7:X})\n{8,-25} {9} (0x{9:X})\n",
                     "DATABASE:", db.Config.Path,
                     "WRITER CHECKPOINT:", db.Config.WriterCheckpoint.Read(),
                     "CHASER CHECKPOINT:", db.Config.ChaserCheckpoint.Read(),
                     "EPOCH CHECKPOINT:", db.Config.EpochCheckpoint.Read(),
                     "TRUNCATE CHECKPOINT:", db.Config.TruncateCheckpoint.Read());

            var enabledNodeSubsystems = runProjections >= RunProjections.System
                ? new[] { NodeSubsystems.Projections }
                : new NodeSubsystems[0];

            _projections = new Projections.Core.ProjectionsSubsystem(opts.ProjectionThreads, runProjections);
            _node        = new SingleVNode(db, vnodeSettings, dbVerifyHashes, opts.MaxMemTableSize, _projections);
            RegisterWebControllers(enabledNodeSubsystems);
            RegisterUIProjections();
        }
예제 #4
0
    public void LoadFromDisk(Vector2DInt inChunkPosition)
    {
        // Open chunk save file
        string chunkFilePath = Constants.Terrain.CHUNK_SAVE_FOLDER + "\\" + inChunkPosition.ToString() + ".chunk";

        using (FileStream stream = FileStreamExtensions.LoadAndWaitUntilLoaded(chunkFilePath, FileMode.Open))
            using (BinaryReader reader = new BinaryReader(stream))
            {
                // Create tile array
                int chunkSize = Constants.Terrain.CHUNK_SIZE;
                SetTiles(new Tile[chunkSize, chunkSize]);

                // Load all tiles from disk
                for (int y = 0; y < chunkSize; y++)
                {
                    for (int x = 0; x < chunkSize; x++)
                    {
                        Vector2DInt tileLocalPosition = new Vector2DInt(x, y);
                        Terrain     tileTerrain       = new Terrain((TerrainType)reader.ReadUInt16()); // Read: Terrain type

                        _tiles[x, y] = new Tile(tileLocalPosition, inChunkPosition, tileTerrain);
                    }
                }

                // Load and place all furnitures
                int numFurnitures = reader.ReadInt32();                                  // Read: Furniture count
                for (int i = 0; i < numFurnitures; i++)
                {
                    Furniture loadedFurniture = new Furniture(reader);                   // Read: Furniture

                    // TODO: Check if there's a furniture within the target area. If so, take that one and place it on itself.
                    WorldChunkManager.instance.PlaceFurniture(loadedFurniture.position, loadedFurniture);
                }

                // TODO: Load the queue of all the furnitures that should be replaced. The queue should just hold furniture type and position. Get the furniture at the saved position and save it on top of itself

                MultiThreader.InvokeOnMain(() => _dirtyFlags.Add(ChunkDirtyFlags.Terrain, ref _dirtyFlags));
            }
    }
예제 #5
0
        public MiniClusterNode(
            string pathname, int debugIndex, IPEndPoint internalTcp, IPEndPoint internalTcpSec, IPEndPoint internalHttp,
            IPEndPoint externalTcp, IPEndPoint externalTcpSec, IPEndPoint externalHttp, IPEndPoint[] gossipSeeds,
            ISubsystem[] subsystems = null, int?chunkSize = null, int?cachedChunkSize = null,
            bool enableTrustedAuth  = false, bool skipInitializeStandardUsersCheck = true, int memTableSize = 1000,
            bool inMemDb            = true, bool disableFlushToDisk = false, bool readOnlyReplica = false)
        {
            if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
            {
                AppContext.SetSwitch("System.Net.Http.SocketsHttpHandler.Http2UnencryptedSupport",
                                     true);    //TODO JPB Remove this sadness when dotnet core supports kestrel + http2 on macOS
            }

            RunningTime.Start();
            RunCount += 1;

            DebugIndex = debugIndex;

            _dbPath = Path.Combine(
                pathname,
                string.Format(
                    "mini-cluster-node-db-{0}-{1}-{2}", externalTcp.Port, externalTcpSec.Port, externalHttp.Port));

            Directory.CreateDirectory(_dbPath);
            FileStreamExtensions.ConfigureFlush(disableFlushToDisk);
            Db =
                new TFChunkDb(
                    CreateDbConfig(chunkSize ?? ChunkSize, _dbPath, cachedChunkSize ?? CachedChunkSize, inMemDb));

            InternalTcpEndPoint    = internalTcp;
            InternalTcpSecEndPoint = internalTcpSec;
            InternalHttpEndPoint   = internalHttp;

            ExternalTcpEndPoint    = externalTcp;
            ExternalTcpSecEndPoint = externalTcpSec;
            ExternalHttpEndPoint   = externalHttp;

            var certificate        = ssl_connections.GetCertificate();
            var disableInternalTls = !ssl_connections.IsValidCertificate(certificate);             //use internal TLS only if CA certificate is installed

            var singleVNodeSettings = new ClusterVNodeSettings(
                Guid.NewGuid(), debugIndex, InternalTcpEndPoint, InternalTcpSecEndPoint, ExternalTcpEndPoint,
                ExternalTcpSecEndPoint, InternalHttpEndPoint, ExternalHttpEndPoint,
                new Data.GossipAdvertiseInfo(InternalTcpEndPoint, InternalTcpSecEndPoint,
                                             ExternalTcpEndPoint, ExternalTcpSecEndPoint,
                                             InternalHttpEndPoint, ExternalHttpEndPoint,
                                             null, null, 0, 0), enableTrustedAuth,
                certificate, 1, false,
                "", gossipSeeds, TFConsts.MinFlushDelayMs, 3, 2, 2, TimeSpan.FromSeconds(10), TimeSpan.FromSeconds(10),
                disableInternalTls, false, TimeSpan.FromHours(1), StatsStorage.None, 0,
                new InternalAuthenticationProviderFactory(), new LegacyAuthorizationProviderFactory(), disableScavengeMerging: true, scavengeHistoryMaxAge: 30,
                adminOnPublic: true,
                statsOnPublic: true, gossipOnPublic: true, gossipInterval: TimeSpan.FromSeconds(2),
                gossipAllowedTimeDifference: TimeSpan.FromSeconds(1), gossipTimeout: TimeSpan.FromSeconds(3),
                extTcpHeartbeatTimeout: TimeSpan.FromSeconds(2), extTcpHeartbeatInterval: TimeSpan.FromSeconds(2),
                intTcpHeartbeatTimeout: TimeSpan.FromSeconds(2), intTcpHeartbeatInterval: TimeSpan.FromSeconds(2),
                deadMemberRemovalPeriod: TimeSpan.FromSeconds(1800),
                verifyDbHash: false, maxMemtableEntryCount: memTableSize,
                hashCollisionReadLimit: Opts.HashCollisionReadLimitDefault,
                startStandardProjections: false, disableHTTPCaching: false, logHttpRequests: false,
                connectionPendingSendBytesThreshold: Opts.ConnectionPendingSendBytesThresholdDefault,
                connectionQueueSizeThreshold: Opts.ConnectionQueueSizeThresholdDefault,
                readOnlyReplica: readOnlyReplica,
                ptableMaxReaderCount: Constants.PTableMaxReaderCountDefault,
                enableExternalTCP: true,
                createHttpMessageHandler: () => new SocketsHttpHandler {
                SslOptions = new SslClientAuthenticationOptions {
                    RemoteCertificateValidationCallback = delegate { return(true); }
                }
            },
                gossipOverHttps: UseHttpsInternally());

            _isReadOnlyReplica = readOnlyReplica;

            Log.Information(
                "\n{0,-25} {1} ({2}/{3}, {4})\n" + "{5,-25} {6} ({7})\n" + "{8,-25} {9} ({10}-bit)\n"
                + "{11,-25} {12}\n" + "{13,-25} {14}\n" + "{15,-25} {16}\n" + "{17,-25} {18}\n" + "{19,-25} {20}\n\n",
                "ES VERSION:", VersionInfo.Version, VersionInfo.Branch, VersionInfo.Hashtag, VersionInfo.Timestamp,
                "OS:", OS.OsFlavor, Environment.OSVersion, "RUNTIME:", OS.GetRuntimeVersion(),
                Marshal.SizeOf(typeof(IntPtr)) * 8, "GC:",
                GC.MaxGeneration == 0
                                        ? "NON-GENERATION (PROBABLY BOEHM)"
                                        : string.Format("{0} GENERATIONS", GC.MaxGeneration + 1), "DBPATH:", _dbPath, "ExTCP ENDPOINT:",
                ExternalTcpEndPoint, "ExTCP SECURE ENDPOINT:", ExternalTcpSecEndPoint, "ExHTTP ENDPOINT:",
                ExternalHttpEndPoint);

            Node = new ClusterVNode(Db, singleVNodeSettings,
                                    infoController: new InfoController(null, ProjectionType.None), subsystems: subsystems,
                                    gossipSeedSource: new KnownEndpointGossipSeedSource(gossipSeeds));
            Node.ExternalHttpService.SetupController(new TestController(Node.MainQueue));

            _host = new WebHostBuilder()
                    .UseKestrel(o => {
                o.Listen(InternalHttpEndPoint, options => {
                    if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
                    {
                        options.Protocols = HttpProtocols.Http2;
                    }
                    else
                    {
                        options.UseHttps();
                    }
                });
                o.Listen(ExternalHttpEndPoint);
            })
                    .UseStartup(Node.Startup)
                    .Build();

            _kestrelTestServer = new TestServer(new WebHostBuilder()
                                                .UseKestrel()
                                                .UseStartup(Node.Startup));
        }
예제 #6
0
        protected override void Create(ClusterNodeOptions opts)
        {
            var dbPath = Path.GetFullPath(ResolveDbPath(opts.DbPath, opts.ExternalHttpPort));

            if (!opts.InMemDb)
            {
                _dbLock = new ExclusiveDbLock(dbPath);
                if (!_dbLock.Acquire())
                {
                    throw new Exception(string.Format("Couldn't acquire exclusive lock on DB at '{0}'.", dbPath));
                }
            }
            _clusterNodeMutex = new ClusterNodeMutex();
            if (!_clusterNodeMutex.Acquire())
            {
                throw new Exception(string.Format("Couldn't acquire exclusive Cluster Node mutex '{0}'.", _clusterNodeMutex.MutexName));
            }

            var dbConfig = CreateDbConfig(dbPath, opts.CachedChunks, opts.ChunksCacheSize, opts.InMemDb);

            FileStreamExtensions.ConfigureFlush(disableFlushToDisk: opts.UnsafeDisableFlushToDisk);
            var db            = new TFChunkDb(dbConfig);
            var vNodeSettings = GetClusterVNodeSettings(opts);

            IGossipSeedSource gossipSeedSource;

            if (opts.DiscoverViaDns)
            {
                gossipSeedSource = new DnsGossipSeedSource(opts.ClusterDns, opts.ClusterGossipPort);
            }
            else
            {
                if (opts.GossipSeeds.Length == 0)
                {
                    if (opts.ClusterSize > 1)
                    {
                        Log.Error(string.Format("DNS discovery is disabled, but no gossip seed endpoints have been specified. " +
                                                "Specify gossip seeds using the --{0} command line option.", Opts.GossipSeedCmd));
                    }
                    else
                    {
                        Log.Info(string.Format("DNS discovery is disabled, but no gossip seed endpoints have been specified. Since" +
                                               "the cluster size is set to 1, this may be intentional. Gossip seeds can be specified" +
                                               "seeds using the --{0} command line option.", Opts.GossipSeedCmd));
                    }
                }

                gossipSeedSource = new KnownEndpointGossipSeedSource(opts.GossipSeeds);
            }

            var dbVerifyHashes = !opts.SkipDbVerify;
            var runProjections = opts.RunProjections;

            Log.Info("\n{0,-25} {1}\n"
                     + "{2,-25} {3}\n"
                     + "{4,-25} {5} (0x{5:X})\n"
                     + "{6,-25} {7} (0x{7:X})\n"
                     + "{8,-25} {9} (0x{9:X})\n"
                     + "{10,-25} {11} (0x{11:X})\n",
                     "INSTANCE ID:", vNodeSettings.NodeInfo.InstanceId,
                     "DATABASE:", db.Config.Path,
                     "WRITER CHECKPOINT:", db.Config.WriterCheckpoint.Read(),
                     "CHASER CHECKPOINT:", db.Config.ChaserCheckpoint.Read(),
                     "EPOCH CHECKPOINT:", db.Config.EpochCheckpoint.Read(),
                     "TRUNCATE CHECKPOINT:", db.Config.TruncateCheckpoint.Read());

            var enabledNodeSubsystems = runProjections >= RunProjections.System
                ? new[] { NodeSubsystems.Projections }
                : new NodeSubsystems[0];

            _projections = new Projections.Core.ProjectionsSubsystem(opts.ProjectionThreads, opts.RunProjections);
            _node        = new ClusterVNode(db, vNodeSettings, gossipSeedSource, dbVerifyHashes, opts.MaxMemTableSize, _projections);
            RegisterWebControllers(enabledNodeSubsystems, vNodeSettings);
            RegisterUiProjections();
        }
예제 #7
0
        public MiniNode(string pathname,
                        int?tcpPort             = null, int?tcpSecPort = null, int?httpPort = null,
                        ISubsystem[] subsystems = null,
                        int?chunkSize           = null, int?cachedChunkSize = null, bool enableTrustedAuth = false, bool skipInitializeStandardUsersCheck = true,
                        int memTableSize        = 1000,
                        bool inMemDb            = true, bool disableFlushToDisk = false)
        {
            if (_running)
            {
                throw new Exception("Previous MiniNode is still running!!!");
            }
            _running = true;

            RunningTime.Start();
            RunCount += 1;

            IPAddress ip = IPAddress.Loopback; //GetLocalIp();

            int extTcpPort    = tcpPort ?? PortsHelper.GetAvailablePort(ip);
            int extSecTcpPort = tcpSecPort ?? PortsHelper.GetAvailablePort(ip);
            int extHttpPort   = httpPort ?? PortsHelper.GetAvailablePort(ip);
            int intTcpPort    = PortsHelper.GetAvailablePort(ip);
            int intSecTcpPort = PortsHelper.GetAvailablePort(ip);
            int intHttpPort   = PortsHelper.GetAvailablePort(ip);

            _dbPath = Path.Combine(pathname, string.Format("mini-node-db-{0}-{1}-{2}", extTcpPort, extSecTcpPort, extHttpPort));
            Directory.CreateDirectory(_dbPath);
            FileStreamExtensions.ConfigureFlush(disableFlushToDisk);
            Db = new TFChunkDb(CreateDbConfig(chunkSize ?? ChunkSize, _dbPath, cachedChunkSize ?? CachedChunkSize, inMemDb));

            TcpEndPoint       = new IPEndPoint(ip, extTcpPort);
            TcpSecEndPoint    = new IPEndPoint(ip, extSecTcpPort);
            HttpEndPoint      = new IPEndPoint(ip, extHttpPort);
            IntTcpEndPoint    = new IPEndPoint(ip, intTcpPort);
            IntSecTcpEndPoint = new IPEndPoint(ip, intSecTcpPort);
            IntHttpEndPoint   = new IPEndPoint(ip, intHttpPort);
            var vNodeSettings = new ClusterVNodeSettings(Guid.NewGuid(),
                                                         0,
                                                         IntTcpEndPoint,
                                                         IntSecTcpEndPoint,
                                                         TcpEndPoint,
                                                         TcpSecEndPoint,
                                                         IntHttpEndPoint,
                                                         HttpEndPoint,
                                                         new [] { HttpEndPoint.ToHttpUrl() },
                                                         enableTrustedAuth,
                                                         ssl_connections.GetCertificate(),
                                                         1,
                                                         false,
                                                         "whatever",
                                                         new IPEndPoint[] {},
                                                         TFConsts.MinFlushDelayMs,
                                                         1,
                                                         1,
                                                         1,
                                                         TimeSpan.FromSeconds(2),
                                                         TimeSpan.FromSeconds(2),
                                                         false,
                                                         "",
                                                         false,
                                                         TimeSpan.FromHours(1),
                                                         StatsStorage.None,
                                                         1,
                                                         new InternalAuthenticationProviderFactory(),
                                                         true,
                                                         true,
                                                         true,
                                                         false,
                                                         TimeSpan.FromSeconds(30),
                                                         TimeSpan.FromSeconds(30),
                                                         TimeSpan.FromSeconds(10),
                                                         TimeSpan.FromSeconds(10),
                                                         TimeSpan.FromSeconds(10),
                                                         TimeSpan.FromSeconds(10),
                                                         TimeSpan.FromSeconds(10),
                                                         false,
                                                         memTableSize);

            Log.Info("\n{0,-25} {1} ({2}/{3}, {4})\n"
                     + "{5,-25} {6} ({7})\n"
                     + "{8,-25} {9} ({10}-bit)\n"
                     + "{11,-25} {12}\n"
                     + "{13,-25} {14}\n"
                     + "{15,-25} {16}\n"
                     + "{17,-25} {18}\n"
                     + "{19,-25} {20}\n\n",
                     "ES VERSION:", VersionInfo.Version, VersionInfo.Branch, VersionInfo.Hashtag, VersionInfo.Timestamp,
                     "OS:", OS.OsFlavor, Environment.OSVersion,
                     "RUNTIME:", OS.GetRuntimeVersion(), Marshal.SizeOf(typeof(IntPtr)) * 8,
                     "GC:", GC.MaxGeneration == 0 ? "NON-GENERATION (PROBABLY BOEHM)" : string.Format("{0} GENERATIONS", GC.MaxGeneration + 1),
                     "DBPATH:", _dbPath,
                     "TCP ENDPOINT:", TcpEndPoint,
                     "TCP SECURE ENDPOINT:", TcpSecEndPoint,
                     "HTTP ENDPOINT:", HttpEndPoint);
            Node = new ClusterVNode(Db, vNodeSettings, new KnownEndpointGossipSeedSource(new [] { HttpEndPoint }), new InfoController(null), subsystems);

            Node.ExternalHttpService.SetupController(new TestController(Node.MainQueue));
        }