private async Task HandleShutdownDanglingSessionsAsync(Context context)
        {
            try
            {
                if (_sessionHandles.Any())
                {
                    var sessionInfoList = new List <HibernatedSessionInfo>(_sessionHandles.Count);

                    foreach (var(sessionId, handle) in _sessionHandles)
                    {
                        TSession session = handle.Session;

                        if (session is IHibernateContentSession hibernateSession)
                        {
                            var pinnedContentHashes = hibernateSession.EnumeratePinnedContentHashes().Select(x => x.Serialize()).ToList();
                            Tracer.Debug(context, $"Hibernating session {DescribeSession(sessionId, handle)}.");
                            sessionInfoList.Add(new HibernatedSessionInfo(
                                                    sessionId,
                                                    handle.SessionName,
                                                    handle.ImplicitPin,
                                                    handle.CacheName,
                                                    pinnedContentHashes,
                                                    handle.SessionExpirationUtcTicks,
                                                    handle.SessionCapabilities));
                        }
                        else
                        {
                            Tracer.Warning(context, $"Shutdown of non-hibernating dangling session id={sessionId}");
                        }

                        await session.ShutdownAsync(context).ThrowIfFailure();

                        session.Dispose();
                    }

                    if (sessionInfoList.Any())
                    {
                        var hibernatedSessions = new HibernatedSessions(sessionInfoList);

                        try
                        {
                            var sw = Stopwatch.StartNew();
                            await hibernatedSessions.WriteAsync(FileSystem, Config.DataRootPath);

                            sw.Stop();
                            Tracer.Debug(
                                context, $"Wrote hibernated sessions to root=[{Config.DataRootPath}] in {sw.Elapsed.TotalMilliseconds}ms");
                        }
                        catch (Exception exception)
                        {
                            Tracer.Warning(context, $"Failed to write hibernated sessions root=[{Config.DataRootPath}]: {exception.ToString()}");
                            Tracer.Error(context, exception);
                        }
                    }

                    _sessionHandles.Clear();
                }
            }
            catch (Exception exception)
            {
                Tracer.Error(context, exception, "Failed to store hibernated sessions");
            }
        }
Example #2
0
        /// <nodoc />
        public static async Task HibernateSessionsAsync(
            Context context,
            IDictionary <int, ISessionHandle <IContentSession, LocalContentServerSessionData> > sessionHandles,
            LocalServerConfiguration config,
            Tracer tracer,
            IAbsFileSystem fileSystem)
        {
            var sessionInfoList = new List <HibernatedContentSessionInfo>(sessionHandles.Count);

            foreach (var(sessionId, handle) in sessionHandles)
            {
                IContentSession session = handle.Session;

                if (session is IHibernateContentSession hibernateSession)
                {
                    if (config.ShutdownEvictionBeforeHibernation)
                    {
                        // Calling shutdown of eviction before hibernating sessions to prevent possible race condition of evicting pinned content
                        await hibernateSession.ShutdownEvictionAsync(context).ThrowIfFailure();
                    }

                    var pinnedContentHashes = hibernateSession.EnumeratePinnedContentHashes().Select(x => x.Serialize()).ToList();

                    tracer.Debug(context, $"Hibernating session {handle.ToString(sessionId)}.");
                    sessionInfoList.Add(new HibernatedContentSessionInfo(
                                            sessionId,
                                            handle.SessionData.Name,
                                            handle.SessionData.ImplicitPin,
                                            handle.CacheName,
                                            pinnedContentHashes,
                                            handle.SessionExpirationUtcTicks,
                                            handle.SessionData.Capabilities));
                }
                else
                {
                    tracer.Warning(context, $"Shutdown of non-hibernating dangling session id={sessionId}");
                }

                await session.ShutdownAsync(context).ThrowIfFailure();

                session.Dispose();
            }

            if (sessionInfoList.Any())
            {
                var hibernatedSessions = new HibernatedSessions <HibernatedContentSessionInfo>(sessionInfoList);

                try
                {
                    var sw = Stopwatch.StartNew();
                    await hibernatedSessions.WriteAsync(fileSystem, config.DataRootPath, HibernatedSessionsFileName);

                    sw.Stop();
                    tracer.Debug(
                        context, $"Wrote hibernated sessions to root=[{config.DataRootPath}] in {sw.Elapsed.TotalMilliseconds}ms");
                }
                catch (Exception exception)
                {
                    tracer.Warning(context, $"Failed to write hibernated sessions root=[{config.DataRootPath}]: {exception}");
                    tracer.Error(context, exception);
                }
            }
        }