bin/projects/dbatools/dbatools/Connection/PSSessionContainer.cs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
using System;
using System.Collections.Generic;
using System.Linq;
using System.Management.Automation.Runspaces;
using System.Text;
using System.Threading.Tasks;

namespace Sqlcollaborative.Dbatools.Connection
{
    /// <summary>
    /// The container that lists all sessions for a given runspace
    /// </summary>
    public class PSSessionContainer
    {
        /// <summary>
        /// The runspace that owns the sessions
        /// </summary>
        public readonly Guid Runspace;

        /// <summary>
        /// The count of expired sessions registered
        /// </summary>
        public int CountExpired { get { return GetExpiredNames().Count; } }

        /// <summary>
        /// List of sessions and their associated computer names
        /// </summary>
        public Dictionary<string, PSSession> Sessions = new Dictionary<string, PSSession>();

        /// <summary>
        /// List of timestamps, when the last command was run against them
        /// </summary>
        public Dictionary<string, DateTime> ConnectionTimestamps = new Dictionary<string, DateTime>();

        /// <summary>
        /// Creates a list of sessions the current runspace is connected to.
        /// </summary>
        /// <param name="Runspace">The Guid of the runspace that is the owner of the registered sessions</param>
        public PSSessionContainer(Guid Runspace)
        {
            this.Runspace = Runspace;
        }

        /// <summary>
        /// Returns the requested session.
        /// </summary>
        /// <param name="ComputerName">The name of the host whose connection to retrieve</param>
        /// <returns>The established connection to the host, null if none exists.</returns>
        public PSSession Get(string ComputerName)
        {
            if (Sessions.ContainsKey(ComputerName.ToLower()))
                return Sessions[ComputerName.ToLower()];
            return null;
        }

        /// <summary>
        /// Sets a session and writes its timestamp to the cache
        /// </summary>
        /// <param name="ComputerName">The hostname it connects to.</param>
        /// <param name="Session">The session that is being registered.</param>
        public void Set(string ComputerName, PSSession Session)
        {
            if (!ConnectionHost.PSSessionCacheEnabled)
                return;
            Sessions[ComputerName.ToLower()] = Session;
            ConnectionTimestamps[ComputerName.ToLower()] = DateTime.Now;
        }

        /// <summary>
        /// Returns the name of hostnames with expired sessions
        /// </summary>
        /// <returns>THe hostnames whose session has expired</returns>
        public List<string> GetExpiredNames()
        {
            List<string> expired = new List<string>();

            foreach (string key in ConnectionTimestamps.Keys)
                if (ConnectionTimestamps[key] + ConnectionHost.PSSessionTimeout < DateTime.Now && Sessions[key] != null && Sessions[key].Availability != RunspaceAvailability.Busy)
                    expired.Add(key);

            return expired;
        }

        /// <summary>
        /// Removes an expired session from the cache, an returns it, so it can be properly closed.
        /// </summary>
        /// <returns>Returns a session to disconnect</returns>
        public PSSession PurgeExpiredSession()
        {
            foreach (string key in ConnectionTimestamps.Keys)
            {
                if (ConnectionTimestamps[key] + ConnectionHost.PSSessionTimeout < DateTime.Now && Sessions[key] != null && Sessions[key].Availability != RunspaceAvailability.Busy)
                {
                    PSSession session = Sessions[key];
                    Sessions.Remove(key);
                    ConnectionTimestamps.Remove(key);
                    return session;
                }
            }
            return null;
        }
    }
}