Example #1
0
        /// <summary>
        ///     Serialize hibernated session information to the standard filename in the given directory.
        /// </summary>
        public static async Task WriteProtectedAsync <TInfo>(this HibernatedSessions <TInfo> sessions, IAbsFileSystem fileSystem, AbsolutePath rootPath, string fileName)
        {
            Contract.Requires(fileSystem != null);
            Contract.Requires(rootPath != null);

            // Due to abnormal process termination, the file that we'll be writing can be corrupted.
            // To prevent this issue we first write the file into a temporary location and then we "move it" into a final location.

            using (var tempFolder = new DisposableDirectory(fileSystem, rootPath / "Temp"))
            {
                var jsonTempPath = tempFolder.CreateRandomFileName();
                var jsonPath     = rootPath / fileName;

                using (var memoryStream = new MemoryStream())
                {
                    sessions.SerializeToJSON(memoryStream);

                    var bytes = memoryStream.ToArray();

                    var protectedBytes = ProtectedData.Protect(bytes, optionalEntropy: null, DataProtectionScope.CurrentUser);

                    using var fileStream = await fileSystem.OpenSafeAsync(jsonTempPath, FileAccess.Write, FileMode.Create, FileShare.None);

                    await fileStream.Stream.WriteAsync(protectedBytes, 0, protectedBytes.Length);
                }

                fileSystem.MoveFile(jsonTempPath, jsonPath, replaceExisting: true);
            }
        }
Example #2
0
        /// <summary>
        ///     Serialize hibernated session information to the standard filename in the given directory.
        /// </summary>
        public static void Write <TInfo>(this HibernatedSessions <TInfo> sessions, IAbsFileSystem fileSystem, AbsolutePath rootPath, string fileName)
        {
            Contract.Requires(rootPath != null);

            // Due to abnormal process termination, the file that we'll be writing can be corrupted.
            // To prevent this issue we first write the file into a temporary location and then we "move it" into a final location.

            using (var tempFolder = new DisposableDirectory(fileSystem, rootPath / "Temp"))
            {
                var jsonTempPath = tempFolder.CreateRandomFileName();
                var jsonPath     = rootPath / fileName;

                using (var stream = fileSystem.Open(jsonTempPath, FileAccess.Write, FileMode.Create, FileShare.None))
                {
                    sessions.SerializeToJSON(stream);
                }

                fileSystem.MoveFile(jsonTempPath, jsonPath, replaceExisting: true);
            }
        }
        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 #4
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. {sessionId.AsTraceableSessionId()}");
                }

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

                session.Dispose();
            }

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

                try
                {
                    var sw = Stopwatch.StartNew();
                    hibernatedSessions.Write(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.Error(context, exception, $"Failed to write hibernated sessions root=[{config.DataRootPath}]");
                }
            }
        }