Beispiel #1
0
        public async Task Roundtrip()
        {
            using (var directory = new DisposableDirectory(FileSystem))
            {
                const Capabilities capabilities = Capabilities.Heartbeat;
                var pins            = ContentHashes.Select(x => x.Serialize()).ToList();
                var expirationTicks = DateTime.UtcNow.Ticks;
                var sessionInfo     = new HibernatedSessionInfo(1, SessionName, ImplicitPin.None, CacheName, pins, expirationTicks, capabilities);
                var sessions1       = new HibernatedSessions(new List <HibernatedSessionInfo> {
                    sessionInfo
                });
                await sessions1.WriteAsync(FileSystem, directory.Path);

                FileSystem.HibernatedSessionsExists(directory.Path).Should().BeTrue();

                var fileSize = FileSystem.GetFileSize(directory.Path / HibernatedSessionsExtensions.FileName);
                fileSize.Should().BeGreaterThan(0);

                var sessions2 = await FileSystem.ReadHibernatedSessionsAsync(directory.Path);

                sessions2.Sessions.Count.Should().Be(1);
                sessions2.Sessions[0].Pins.Count.Should().Be(ContentHashCount);
                sessions2.Sessions[0].ExpirationUtcTicks.Should().Be(expirationTicks);
                sessions2.Sessions[0].Capabilities.Should().Be(capabilities);
                await FileSystem.DeleteHibernatedSessions(directory.Path);
            }
        }
Beispiel #2
0
        public async Task RoundtripSessionsWithSameName()
        {
            const int count = 3;

            using (var directory = new DisposableDirectory(FileSystem))
            {
                var sessionInfoList = new List <HibernatedSessionInfo>();
                foreach (var i in Enumerable.Range(0, count))
                {
                    List <string> pins = ContentHashes.Select(x => x.Serialize()).ToList();
                    sessionInfoList.Add(new HibernatedSessionInfo(i, SessionName, ImplicitPin.None, CacheName, pins, DateTime.UtcNow.Ticks, Capabilities.None));
                }

                var sessions1 = new HibernatedSessions(sessionInfoList);
                await sessions1.WriteAsync(FileSystem, directory.Path);

                FileSystem.HibernatedSessionsExists(directory.Path).Should().BeTrue();

                var sessions2 = await FileSystem.ReadHibernatedSessionsAsync(directory.Path);

                sessions2.Sessions.Count.Should().Be(count);
                sessions2.Sessions.All(s => s.Pins.Count == ContentHashCount).Should().BeTrue();
                sessions2.Sessions.All(s => s.Session == SessionName).Should().BeTrue();
                sessions2.Sessions.All(s => s.Cache == CacheName).Should().BeTrue();
                await FileSystem.DeleteHibernatedSessions(directory.Path);
            }
        }
        public async Task Roundtrip()
        {
            var fileName = $"{Guid.NewGuid()}.json";

            using (var directory = new DisposableDirectory(FileSystem))
            {
                var sessionId        = 42;
                var serializedConfig = "Foo";
                var pat = Guid.NewGuid().ToString();

                var numOperations = 3;
                var operations    = Enumerable.Range(0, numOperations)
                                    .Select(_ => generateRandomOperation())
                                    .ToList();

                var sessionInfo = new HibernatedCacheSessionInfo(sessionId, serializedConfig, pat, operations);
                var sessions1   = new HibernatedSessions <HibernatedCacheSessionInfo>(new List <HibernatedCacheSessionInfo> {
                    sessionInfo
                });
                await sessions1.WriteAsync(FileSystem, directory.Path, fileName);

                FileSystem.HibernatedSessionsExists(directory.Path, fileName).Should().BeTrue();

                var fileSize = FileSystem.GetFileSize(directory.Path / fileName);
                fileSize.Should().BeGreaterThan(0);

                var sessions2 = await FileSystem.ReadHibernatedSessionsAsync <HibernatedCacheSessionInfo>(directory.Path, fileName);

                sessions2.Sessions.Count.Should().Be(1);
                sessions2.Sessions[0].Id.Should().Be(sessionId);
                sessions2.Sessions[0].SerializedSessionConfiguration.Should().Be(serializedConfig);
                sessions2.Sessions[0].Pat.Should().Be(pat);
                sessions2.Sessions[0].PendingPublishingOperations.Should().BeEquivalentTo(operations);

                await FileSystem.DeleteHibernatedSessions(directory.Path, fileName);

                PublishingOperation generateRandomOperation()
                {
                    var amountOfHashes  = 3;
                    var hashes          = Enumerable.Range(0, amountOfHashes).Select(_ => ContentHash.Random()).ToArray();
                    var contentHashList = new ContentHashList(hashes);
                    var determinism     = CacheDeterminism.ViaCache(CacheDeterminism.NewCacheGuid(), DateTime.UtcNow.AddMilliseconds(ThreadSafeRandom.Generator.Next()));
                    var contentHashListWithDeterminism = new ContentHashListWithDeterminism(contentHashList, determinism);

                    var fingerprint       = new Fingerprint(ContentHash.Random().ToByteArray());
                    var selector          = new Selector(ContentHash.Random());
                    var strongFingerprint = new StrongFingerprint(fingerprint, selector);

                    return(new PublishingOperation
                    {
                        ContentHashListWithDeterminism = contentHashListWithDeterminism,
                        StrongFingerprint = strongFingerprint
                    });
                }
            }
        }
Beispiel #4
0
        protected override async Task HibernateSessionsAsync(
            Context context,
            IDictionary <int, ISessionHandle <ICacheSession, LocalCacheServerSessionData> > sessionHandles)
        {
            var sessionInfoList = new List <HibernatedCacheSessionInfo>(sessionHandles.Count);

            foreach (var keyValuePair in sessionHandles)
            {
                var id     = keyValuePair.Key;
                var handle = keyValuePair.Value;
                if (handle.Session is IHibernateCacheSession hibernateSession)
                {
                    IList <PublishingOperation>?pending = null;
                    string?serializedConfig             = null;
                    if (handle.SessionData.PublishingConfig is not null)
                    {
                        pending          = hibernateSession.GetPendingPublishingOperations();
                        serializedConfig = DynamicJson.Serialize(handle.SessionData.PublishingConfig);
                    }

                    var info = new HibernatedCacheSessionInfo(
                        id,
                        serializedConfig,
                        handle.SessionData.Pat,
                        pending);

                    sessionInfoList.Add(info);
                }
            }
            var hibernatedSessions = new HibernatedSessions <HibernatedCacheSessionInfo>(sessionInfoList);

            try
            {
                await hibernatedSessions.WriteProtectedAsync(FileSystem, Config.DataRootPath, HibernatedSessionsFileName);
            }
            catch (Exception e) when(e is NotSupportedException)
            {
                Tracer.Debug(context, e, "Failed to protect hibernated sessions because it is not supported by the current OS. " +
                             $"Attempting to hibernate while unprotected.");
                hibernatedSessions.Write(FileSystem, Config.DataRootPath, HibernatedSessionsFileName);
            }

            var contentHandles = new Dictionary <int, ISessionHandle <IContentSession, LocalContentServerSessionData> >(sessionHandles.Count);

            foreach (var keyValuePair in sessionHandles)
            {
                contentHandles[keyValuePair.Key] = keyValuePair.Value;
            }
            await LocalContentServer.HibernateSessionsAsync(context, contentHandles, Config, Tracer, FileSystem);
        }
        public async Task HibernationDataNotLoadedIfStoreStartupFails()
        {
            const string scenario = nameof(HibernationDataNotLoadedIfStoreStartupFails);
            var          fileName = $"{Guid.NewGuid()}.json";

            var context = new Context(Logger);

            using (var directory = new DisposableDirectory(FileSystem))
            {
                var rootPath    = directory.Path;
                var contentHash = ContentHash.Random();

                var pins = new List <string> {
                    contentHash.Serialize()
                };
                var hibernatedSessionInfo = new HibernatedContentSessionInfo(SessionId, SessionName, ImplicitPin.None, CacheName, pins, 0, Capabilities.None);
                var hibernatedSessions    = new HibernatedSessions <HibernatedContentSessionInfo>(new List <HibernatedContentSessionInfo> {
                    hibernatedSessionInfo
                });
                hibernatedSessions.Write(FileSystem, rootPath, fileName);

                var namedCacheRoots = new Dictionary <string, AbsolutePath> {
                    { CacheName, rootPath }
                };

                var grpcPort         = PortExtensions.GetNextAvailablePort();
                var grpcPortFileName = Guid.NewGuid().ToString();

                var configuration = new ServiceConfiguration(namedCacheRoots, rootPath, MaxConnections, GracefulShutdownSeconds, grpcPort, grpcPortFileName);

                Func <AbsolutePath, IContentStore> contentStoreFactory =
                    (path) => new TestFailingContentStore();
                var localContentServerConfiguration = new LocalServerConfiguration(configuration)
                {
                    UnusedSessionHeartbeatTimeout       = TimeSpan.FromSeconds(TimeoutSecs),
                    UnusedSessionTimeout                = TimeSpan.FromSeconds(TimeoutSecs * 4),
                    RequestCallTokensPerCompletionQueue = 10,
                };

                using (var server = new LocalContentServer(FileSystem, Logger, scenario, contentStoreFactory, localContentServerConfiguration))
                {
                    var r = await server.StartupAsync(context);

                    r.ShouldBeError(TestFailingContentStore.FailureMessage);
                    FileSystem.HibernatedSessionsExists(rootPath, fileName).Should().BeTrue("The hibernation data should not have been read/deleted");
                }
            }
        }
        public async Task Roundtrip(bool useProtected)
        {
            var fileName = $"{Guid.NewGuid()}.json";

            using (var directory = new DisposableDirectory(FileSystem))
            {
                const Capabilities capabilities = Capabilities.Heartbeat;
                var pins            = ContentHashes.Select(x => x.Serialize()).ToList();
                var expirationTicks = DateTime.UtcNow.Ticks;
                var sessionInfo     = new HibernatedContentSessionInfo(1, SessionName, ImplicitPin.None, CacheName, pins, expirationTicks, capabilities);
                var sessions1       = new HibernatedSessions <HibernatedContentSessionInfo>(new List <HibernatedContentSessionInfo> {
                    sessionInfo
                });
                if (useProtected)
                {
                    await sessions1.WriteProtectedAsync(FileSystem, directory.Path, fileName);
                }
                else
                {
                    sessions1.Write(FileSystem, directory.Path, fileName);
                }

                FileSystem.HibernatedSessionsExists(directory.Path, fileName).Should().BeTrue();

                var fileSize = FileSystem.GetFileSize(directory.Path / fileName);
                fileSize.Should().BeGreaterThan(0);

                var sessions2 = useProtected
                    ? await FileSystem.ReadProtectedHibernatedSessionsAsync <HibernatedContentSessionInfo>(directory.Path, fileName)
                    : await FileSystem.ReadHibernatedSessionsAsync <HibernatedContentSessionInfo>(directory.Path, fileName);

                sessions2.Sessions.Count.Should().Be(1);
                sessions2.Sessions[0].Pins.Count.Should().Be(ContentHashCount);
                sessions2.Sessions[0].ExpirationUtcTicks.Should().Be(expirationTicks);
                sessions2.Sessions[0].Capabilities.Should().Be(capabilities);
                await FileSystem.DeleteHibernatedSessions(directory.Path, fileName);
            }
        }
Beispiel #7
0
        [Trait("Category", "QTestSkip")] // Skipped
        public async Task RestoredSessionReleasedAfterInactivity()
        {
            const string scenario = nameof(RestoredSessionReleasedAfterInactivity);

            var context = new Context(Logger);

            using (var directory = new DisposableDirectory(FileSystem))
            {
                var rootPath    = directory.Path;
                var contentHash = ContentHash.Random();

                var pins = new List <string> {
                    contentHash.Serialize()
                };
                var hibernatedSessionInfo = new HibernatedSessionInfo(SessionId, SessionName, ImplicitPin.None, CacheName, pins, DateTime.UtcNow.Ticks, Capabilities.None);
                var hibernatedSessions    = new HibernatedSessions(new List <HibernatedSessionInfo> {
                    hibernatedSessionInfo
                });
                await hibernatedSessions.WriteAsync(FileSystem, rootPath);

                var namedCacheRoots = new Dictionary <string, AbsolutePath> {
                    { CacheName, rootPath }
                };

                var grpcPort         = PortExtensions.GetNextAvailablePort();
                var grpcPortFileName = Guid.NewGuid().ToString();

                var configuration = new ServiceConfiguration(namedCacheRoots, rootPath, MaxConnections, GracefulShutdownSeconds, grpcPort, grpcPortFileName);
                var storeConfig   = ContentStoreConfiguration.CreateWithMaxSizeQuotaMB(1);
                Func <AbsolutePath, IContentStore> contentStoreFactory = (path) =>
                                                                         new FileSystemContentStore(
                    FileSystem,
                    SystemClock.Instance,
                    directory.Path,
                    new ConfigurationModel(storeConfig));
                var localContentServerConfiguration = new LocalServerConfiguration(configuration)
                {
                    UnusedSessionHeartbeatTimeout       = TimeSpan.FromSeconds(TimeoutSecs),
                    RequestCallTokensPerCompletionQueue = 10,
                };

                using (var server = new LocalContentServer(FileSystem, Logger, scenario, contentStoreFactory, localContentServerConfiguration))
                {
                    var r1 = await server.StartupAsync(context);

                    r1.ShouldBeSuccess();

                    var beforeIds = server.GetSessionIds();
                    beforeIds.Should().Contain(SessionId);

                    // Wait one period to ensure that it times out, another to ensure that the checker finds it, and another to give it time to release it.
                    await Task.Delay(TimeSpan.FromSeconds(TimeoutSecs * 3));

                    var afterIds = server.GetSessionIds();
                    afterIds.Count.Should().Be(0);

                    var r2 = await server.ShutdownAsync(context);

                    r2.ShouldBeSuccess();
                }
            }
        }