Exemplo n.º 1
0
 private WaitHandle GetExitEvent()
 {
     if (OperatingSystemHelper.IsWindowsOS)
     {
         return(IpcUtilities.GetShutdownWaitHandle(_scenario));
     }
     else
     {
         // Not supported on non-windows OS. Return no-op wait handle.
         return(CancellationToken.None.WaitHandle);
     }
 }
Exemplo n.º 2
0
        public void SetAndCloseAnOpenHandle()
        {
            var identifier = $"{nameof(IpcUtilitiesTests)}.{nameof(SetAndCloseAnOpenHandle)}";

            using (var shutdownHandle = IpcUtilities.GetShutdownWaitHandle(identifier))
            {
                // Open the handle, set it, and close it. This should not close the outer handle.
                IpcUtilities.SetShutdown(identifier).Should().BeTrue();

                // Validate the outer handle is set but not closed.
                shutdownHandle.WaitOne(100).Should().BeTrue();
            }
        }
Exemplo n.º 3
0
        public void ClosedHandleCannotBeReopened()
        {
            var identifier = $"{nameof(IpcUtilitiesTests)}.{nameof(ClosedHandleCannotBeReopened)}";

            // Set the shutdown handle and immediately close it
            IpcUtilities.SetShutdown(identifier).Should().BeTrue();

            using (var dupShutdownHandle = IpcUtilities.GetShutdownWaitHandle(identifier))
            {
                // The handle should NOT be set
                dupShutdownHandle.WaitOne(100).Should().BeFalse();
            }
        }
Exemplo n.º 4
0
        private static EventWaitHandle CreateShutdownEvent(ILogger logger, string scenario)
        {
            var currentUser = UserUtilities.CurrentUserName();

            logger.Debug($"Creating shutdown event name=[{scenario}] for user=[{currentUser}]");
            var shutdownEvent = IpcUtilities.GetShutdownWaitHandle(scenario);

            if (shutdownEvent.WaitOne(0))
            {
                shutdownEvent.Dispose();
                throw new CacheException($"Shutdown event name=[{scenario}] already exists");
            }

            return(shutdownEvent);
        }
Exemplo n.º 5
0
        public void TwoHandlesWithSameNameAreIdentical()
        {
            var identifier = $"{nameof(IpcUtilitiesTests)}.{nameof(TwoHandlesWithSameNameAreIdentical)}";

            using (var shutdownHandle = IpcUtilities.GetShutdownWaitHandle(identifier))
            {
                // Open the handle for one thread
                shutdownHandle.Set().Should().BeTrue();

                using (var dupShutdownHandle = IpcUtilities.GetShutdownWaitHandle(identifier))
                {
                    // Use handle's signal and reset
                    dupShutdownHandle.WaitOne(100).Should().BeTrue();
                }
            }
        }
Exemplo n.º 6
0
        internal void Service
        (
            [Description("Cache names")] string[] names,
            [Description("Cache root paths")] string[] paths,
            [DefaultValue(DefaultMaxConnections), Description(MaxConnectionsDescription)] uint maxConnections,
            [DefaultValue(DefaultGracefulShutdownSeconds), Description(GracefulShutdownSecondsDescription)] uint gracefulShutdownSeconds,
            [DefaultValue(ServiceConfiguration.GrpcDisabledPort), Description(GrpcPortDescription)] int grpcPort,
            [Description("Name of the memory mapped file used to share GRPC port. 'CASaaS GRPC port' if not specified.")] string grpcPortFileName,
            [DefaultValue(null), Description("Writable directory for service operations (use CWD if null)")] string dataRootPath,
            [DefaultValue(null), Description("Duration of inactivity after which a session will be timed out.")] double?unusedSessionTimeoutSeconds,
            [DefaultValue(null), Description("Duration of inactivity after which a session with a heartbeat will be timed out.")] double?unusedSessionHeartbeatTimeoutSeconds,
            [DefaultValue(false), Description("Stop running service")] bool stop,
            [DefaultValue(Constants.OneMB), Description("Max size quota in MB")] int maxSizeQuotaMB
        )
        {
            Initialize();

            if (stop)
            {
                IpcUtilities.SetShutdown(_scenario);

                return;
            }

            if (names == null || paths == null)
            {
                throw new CacheException("At least one cache name/path is required.");
            }

            if (names.Length != paths.Length)
            {
                throw new CacheException("Mismatching lengths of names/paths arguments.");
            }

            var caches = new Dictionary <string, string>();

            for (var i = 0; i < names.Length; i++)
            {
                caches.Add(names[i], paths[i]);
            }

            var serverDataRootPath = !string.IsNullOrWhiteSpace(dataRootPath)
                ? new AbsolutePath(dataRootPath)
                : new AbsolutePath(Environment.CurrentDirectory);

            var cancellationTokenSource = new CancellationTokenSource();

#if !FEATURE_CORECLR
            var configuration = new ServiceConfiguration(caches, serverDataRootPath, maxConnections, gracefulShutdownSeconds, grpcPort, grpcPortFileName);
            if (!configuration.IsValid)
            {
                throw new CacheException($"Invalid service configuration, error=[{configuration.Error}]");
            }

            var localContentServerConfiguration = new LocalServerConfiguration(configuration);
            if (unusedSessionTimeoutSeconds != null)
            {
                localContentServerConfiguration.UnusedSessionTimeout = TimeSpan.FromSeconds(unusedSessionTimeoutSeconds.Value);
            }

            if (unusedSessionHeartbeatTimeoutSeconds != null)
            {
                localContentServerConfiguration.UnusedSessionHeartbeatTimeout = TimeSpan.FromSeconds(unusedSessionHeartbeatTimeoutSeconds.Value);
            }

            if (_scenario != null)
            {
                _logger.Debug($"scenario=[{_scenario}]");
            }

            var exitSignal = new ManualResetEvent(false);
            Console.CancelKeyPress += (sender, args) =>
            {
                exitSignal.Set();
                args.Cancel = true;
            };

            using (var exitEvent = IpcUtilities.GetShutdownWaitHandle(_scenario))
            {
                var server = new LocalContentServer(
                    _fileSystem,
                    _logger,
                    _scenario,
                    path =>
                    new FileSystemContentStore(
                        _fileSystem,
                        SystemClock.Instance,
                        path,
                        new ConfigurationModel(inProcessConfiguration: ContentStoreConfiguration.CreateWithMaxSizeQuotaMB((uint)maxSizeQuotaMB))),
                    localContentServerConfiguration);

                using (server)
                {
                    var context = new Context(_logger);
                    try
                    {
                        var result = server.StartupAsync(context).Result;
                        if (!result.Succeeded)
                        {
                            throw new CacheException(result.ErrorMessage);
                        }

                        int completedIndex = WaitHandle.WaitAny(new WaitHandle[] { exitSignal, exitEvent });
                        var source         = completedIndex == 0 ? "control-C" : "exit event";
                        _tracer.Always(context, $"Shutdown by {source}.");
                    }
                    finally
                    {
                        var result = server.ShutdownAsync(context).Result;
                        if (!result.Succeeded)
                        {
                            _tracer.Warning(context, $"Failed to shutdown store: {result.ErrorMessage}");
                        }
                    }
                }
            }
#else
            Console.CancelKeyPress += (sender, args) =>
            {
                cancellationTokenSource.Cancel();
                args.Cancel = true;
            };

            var localCasSettings = LocalCasSettings.Default(maxSizeQuotaMB, serverDataRootPath.Path, names[0], (uint)grpcPort);

            var distributedContentSettings = DistributedContentSettings.CreateDisabled();

            var distributedCacheServiceConfiguration = new DistributedCacheServiceConfiguration(localCasSettings, distributedContentSettings);

            // Ensure the computed keyspace is computed based on the hostInfo's StampId
            distributedCacheServiceConfiguration.UseStampBasedIsolation = false;

            var distributedCacheServiceArguments = new DistributedCacheServiceArguments(
                logger: _logger,
                copier: null,
                pathTransformer: null,
                host: new EnvironmentVariableHost(),
                hostInfo: new HostInfo(null, null, new List <string>()),
                cancellation: cancellationTokenSource.Token,
                dataRootPath: serverDataRootPath.Path,
                configuration: distributedCacheServiceConfiguration,
                keyspace: null);

            DistributedCacheServiceFacade.RunAsync(distributedCacheServiceArguments).GetAwaiter().GetResult();

            // Because the facade completes immediately and named wait handles don't exist in CORECLR,
            // completion here is gated on Control+C. In the future, this can be redone with another option,
            // such as a MemoryMappedFile or GRPC heartbeat. This is just intended to be functional.
            cancellationTokenSource.Token.WaitHandle.WaitOne();
#endif
        }