diff --git a/src/Microsoft.PowerShell.Workflow.ServiceCore/AssemblyInfo.cs b/src/Microsoft.PowerShell.Workflow.ServiceCore/AssemblyInfo.cs
deleted file mode 100644
index 944ee1264e..0000000000
--- a/src/Microsoft.PowerShell.Workflow.ServiceCore/AssemblyInfo.cs
+++ /dev/null
@@ -1,27 +0,0 @@
-using System.Reflection;
-using System.Security.Permissions;
-using System.Runtime.CompilerServices;
-using System.Runtime.ConstrainedExecution;
-using System.Diagnostics.CodeAnalysis;
-
-[assembly: AssemblyConfiguration("")]
-[assembly: AssemblyInformationalVersionAttribute (@"10.0.10011.16384")]
-[assembly: ReliabilityContractAttribute(Consistency.MayCorruptAppDomain, Cer.MayFail)]
-[assembly: AssemblyTitle("Microsoft.PowerShell.Workflow.ServiceCore")]
-[assembly: AssemblyDescription("Microsoft.PowerShell.Workflow.ServiceCore")]
-[assembly:AssemblyFileVersionAttribute("3.0.0.0")]
-[assembly:AssemblyVersion("3.0.0.0")]
-
-[module: SuppressMessage("Microsoft.Design", "CA1014:MarkAssembliesWithClsCompliant")]
-[module: SuppressMessage("Microsoft.Naming", "CA1703:ResourceStringsShouldBeSpelledCorrectly", Scope="resource", Target="Resources.resources", MessageId="InlineScript")]
-[module: SuppressMessage("Microsoft.Naming", "CA1703:ResourceStringsShouldBeSpelledCorrectly", Scope="resource", Target="Resources.resources", MessageId="foreach")]
-[module: SuppressMessage("Microsoft.Naming", "CA1703:ResourceStringsShouldBeSpelledCorrectly", Scope="resource", Target="Resources.resources", MessageId="suspendable")]
-
-[assembly:InternalsVisibleTo("M3PTestAutomation,PublicKey=0024000004800000940000000602000000240000525341310004000001000100b5fc90e7027f67871e773a8fde8938c81dd402ba65b9201d60593e96c492651e889cc13f1415ebb53fac1131ae0bd333c5ee6021672d9718ea31a8aebd0da0072f25d87dba6fc90ffd598ed4da35e44c398c454307e8e33b8426143daec9f596836f97c8f74750e5975c64e2189f45def46b2a2b1247adc3652bf5c308055da9")]
-[assembly:InternalsVisibleTo("M3PTestCommon,PublicKey=0024000004800000940000000602000000240000525341310004000001000100b5fc90e7027f67871e773a8fde8938c81dd402ba65b9201d60593e96c492651e889cc13f1415ebb53fac1131ae0bd333c5ee6021672d9718ea31a8aebd0da0072f25d87dba6fc90ffd598ed4da35e44c398c454307e8e33b8426143daec9f596836f97c8f74750e5975c64e2189f45def46b2a2b1247adc3652bf5c308055da9")]
-[assembly:InternalsVisibleTo("VSTS.M3PUnitTest,PublicKey=0024000004800000940000000602000000240000525341310004000001000100b5fc90e7027f67871e773a8fde8938c81dd402ba65b9201d60593e96c492651e889cc13f1415ebb53fac1131ae0bd333c5ee6021672d9718ea31a8aebd0da0072f25d87dba6fc90ffd598ed4da35e44c398c454307e8e33b8426143daec9f596836f97c8f74750e5975c64e2189f45def46b2a2b1247adc3652bf5c308055da9")]
-[assembly:InternalsVisibleTo("VSTS.ActivityTests,PublicKey=0024000004800000940000000602000000240000525341310004000001000100b5fc90e7027f67871e773a8fde8938c81dd402ba65b9201d60593e96c492651e889cc13f1415ebb53fac1131ae0bd333c5ee6021672d9718ea31a8aebd0da0072f25d87dba6fc90ffd598ed4da35e44c398c454307e8e33b8426143daec9f596836f97c8f74750e5975c64e2189f45def46b2a2b1247adc3652bf5c308055da9")]
-[assembly:InternalsVisibleTo("ActivityTests,PublicKey=0024000004800000940000000602000000240000525341310004000001000100eb57e8072e5fa11a7783bde0003e38bec8272f81d965c161b33b2f45404c9c9177a682ee7049400723fc456ea69b638514943375f7c594027477f9d17e8c3535e6491f382308fbf1c7795413456ac88c0c9881ef49ab9789919f5eeabc9149ccb800bbef8f04103ea24b9be1fb923006b0a272c0d8d928bfdbe947a0f3df4a99")]
-[assembly:InternalsVisibleTo("WorkflowCoreTest,PublicKey=0024000004800000940000000602000000240000525341310004000001000100eb57e8072e5fa11a7783bde0003e38bec8272f81d965c161b33b2f45404c9c9177a682ee7049400723fc456ea69b638514943375f7c594027477f9d17e8c3535e6491f382308fbf1c7795413456ac88c0c9881ef49ab9789919f5eeabc9149ccb800bbef8f04103ea24b9be1fb923006b0a272c0d8d928bfdbe947a0f3df4a99")]
-[assembly:InternalsVisibleTo("WorkflowJobsTest,PublicKey=0024000004800000940000000602000000240000525341310004000001000100eb57e8072e5fa11a7783bde0003e38bec8272f81d965c161b33b2f45404c9c9177a682ee7049400723fc456ea69b638514943375f7c594027477f9d17e8c3535e6491f382308fbf1c7795413456ac88c0c9881ef49ab9789919f5eeabc9149ccb800bbef8f04103ea24b9be1fb923006b0a272c0d8d928bfdbe947a0f3df4a99")]
-
diff --git a/src/Microsoft.PowerShell.Workflow.ServiceCore/ServiceCore/WorkflowCore/ActivityCategories.cs b/src/Microsoft.PowerShell.Workflow.ServiceCore/ServiceCore/WorkflowCore/ActivityCategories.cs
deleted file mode 100644
index 5f438fae44..0000000000
--- a/src/Microsoft.PowerShell.Workflow.ServiceCore/ServiceCore/WorkflowCore/ActivityCategories.cs
+++ /dev/null
@@ -1,99 +0,0 @@
-using System;
-using System.Activities;
-using System.ComponentModel;
-using System.Management.Automation;
-using System.Management.Automation.Runspaces;
-using System.Collections.ObjectModel;
-using System.ComponentModel.Design;
-using Microsoft.PowerShell.Workflow;
-
-namespace Microsoft.PowerShell.Activities
-{
- ///
- /// Category attribute for "Activity-Specific Parameters"
- ///
- [AttributeUsage(AttributeTargets.All, AllowMultiple = false, Inherited = true)]
- public sealed class ParameterSpecificCategoryAttribute : CategoryAttribute
- {
- ///
- /// Creates the attribute.
- ///
- public ParameterSpecificCategoryAttribute() : base("") { }
-
- ///
- /// Gets a localized version of the attribute description.
- ///
- /// Not used.
- /// A localized version of the attribute description
- protected override string GetLocalizedString(string value)
- {
- return Resources.ActivityParameterGroup;
- }
- }
-
- ///
- /// Category attribute for "Input and Output"
- ///
- [AttributeUsage(AttributeTargets.All, AllowMultiple = false, Inherited = true)]
- public sealed class InputAndOutputCategoryAttribute : CategoryAttribute
- {
- ///
- /// Creates the attribute.
- ///
- public InputAndOutputCategoryAttribute() : base("") { }
-
- ///
- /// Gets a localized version of the attribute description.
- ///
- /// Not used.
- /// A localized version of the attribute description
- protected override string GetLocalizedString(string value)
- {
- return Resources.InputAndOutputGroup;
- }
- }
-
- ///
- /// Category attribute for "Behavior"
- ///
- [AttributeUsage(AttributeTargets.All, AllowMultiple = false, Inherited = true)]
- public sealed class BehaviorCategoryAttribute : CategoryAttribute
- {
- ///
- /// Creates the attribute.
- ///
- public BehaviorCategoryAttribute() : base("") { }
-
- ///
- /// Gets a localized version of the attribute description.
- ///
- /// Not used.
- /// A localized version of the attribute description
- protected override string GetLocalizedString(string value)
- {
- return CategoryAttribute.Behavior.Category;
- }
- }
-
- ///
- /// Category attribute for "Connectivity"
- ///
- [AttributeUsage(AttributeTargets.All, AllowMultiple = false, Inherited = true)]
- public sealed class ConnectivityCategoryAttribute : CategoryAttribute
- {
- ///
- /// Creates the attribute.
- ///
- public ConnectivityCategoryAttribute() : base("") { }
-
- ///
- /// Gets a localized version of the attribute description.
- ///
- /// Not used.
- /// A localized version of the attribute description
- protected override string GetLocalizedString(string value)
- {
- return Resources.ConnectivityGroup;
- }
- }
-}
diff --git a/src/Microsoft.PowerShell.Workflow.ServiceCore/ServiceCore/WorkflowCore/ActivityHostManager.cs b/src/Microsoft.PowerShell.Workflow.ServiceCore/ServiceCore/WorkflowCore/ActivityHostManager.cs
deleted file mode 100644
index 34efb708c3..0000000000
--- a/src/Microsoft.PowerShell.Workflow.ServiceCore/ServiceCore/WorkflowCore/ActivityHostManager.cs
+++ /dev/null
@@ -1,673 +0,0 @@
-/********************************************************************++
-Copyright (c) Microsoft Corporation. All rights reserved.
---********************************************************************/
-
-using System;
-using System.Collections.Generic;
-using System.Collections.ObjectModel;
-using System.Collections.Concurrent;
-using System.Diagnostics;
-using System.Diagnostics.CodeAnalysis;
-using System.Linq;
-using System.Management.Automation.Runspaces;
-using System.Threading;
-using System.Management.Automation;
-using Microsoft.PowerShell.Activities;
-using System.Management.Automation.Tracing;
-using System.Activities;
-using System.Management.Automation.PerformanceData;
-using System.Management.Automation.Remoting;
-
-namespace Microsoft.PowerShell.Workflow
-{
- internal class ConnectionAsyncResult : IAsyncResult
- {
- #region Private Members
-
- private readonly object _state;
- private readonly AsyncCallback _callback;
- private bool _isCompleted;
- private ManualResetEvent _completedWaitHandle;
- private readonly object _syncObject = new object();
- private Exception _exception;
- private readonly Guid _ownerId;
- #endregion Private Members
-
- #region Internal
-
- internal ConnectionAsyncResult(object state, AsyncCallback callback, Guid ownerId)
- {
- _state = state;
- _ownerId = ownerId;
- _callback = callback;
- }
-
- internal Object State
- {
- get { return _state; }
- }
-
- internal AsyncCallback Callback
- {
- get { return _callback; }
- }
-
- internal ActivityInvoker Invoker { get; set; }
-
- ///
- /// this method is not thread safe
- ///
- internal void SetAsCompleted(Exception exception)
- {
- if (_isCompleted) return;
-
- lock (_syncObject)
- {
- if (_isCompleted) return;
-
- _isCompleted = true;
- _exception = exception;
- if (_completedWaitHandle != null) _completedWaitHandle.Set();
- }
-
- // invoke callback if available
- if (null != _callback)
- _callback(this);
- }
-
- internal Guid OwnerId
- {
- get { return _ownerId; }
- }
-
- internal void EndInvoke()
- {
- AsyncWaitHandle.WaitOne();
- AsyncWaitHandle.Close();
- _completedWaitHandle = null; // allow early GC
-
- if (null != _exception) throw _exception;
- }
-
- #endregion Internal
-
- #region Overrides
-
- ///
- /// Whether the operation represented by this method is
- /// completed
- ///
- public bool IsCompleted
- {
- get { return _isCompleted; }
- }
-
- ///
- /// Wait Handle for the operation
- ///
- public WaitHandle AsyncWaitHandle
- {
- get
- {
- if(null == _completedWaitHandle)
- {
- lock(_syncObject)
- {
- if (null == _completedWaitHandle)
- {
- _completedWaitHandle = new ManualResetEvent(_isCompleted);
- }
- }
- }
-
- return _completedWaitHandle;
- }
- }
-
- ///
- /// Optional user specified state
- ///
- public object AsyncState
- {
- get { return _state; }
- }
-
- ///
- /// Whether this operation completed synchronously
- ///
- public bool CompletedSynchronously
- {
- get { return _completedSynchronously; }
- set { _completedSynchronously = value; }
- }
-
- private bool _completedSynchronously;
-
- #endregion Overrides
- }
-
- ///
- /// Activity Host Manager which will spawn a set of activity
- /// host processes until all of them are used after which
- /// it will start queueing requests
- ///
- /// Whether this class needs to remain public should be
- /// evaluated
- internal sealed class PSOutOfProcessActivityController : PSActivityHostController
- {
- #region Private Members
-
- ///
- /// Stack of available host processes
- ///
- private readonly Collection _hostProcesses = new Collection();
-
- ///
- /// Queue of requests
- ///
- private readonly ConcurrentQueue _requests =
- new ConcurrentQueue();
- private int _isServicing;
- private const int Servicing = 1;
- private const int NotServicing = 0;
- private const int MinActivityHosts = 1;
- private int _busyHosts;
- private readonly Tracer _structuredTracer = new Tracer();
- private readonly PSWorkflowConfigurationProvider _configuration;
- private static readonly PSPerfCountersMgr PerfCountersMgr = PSPerfCountersMgr.Instance;
-
-
- ///
- /// List of requests that need to be invoked again due to process crash
- ///
- private readonly ConcurrentQueue _failedRequests = new ConcurrentQueue();
-
- #endregion Private Members
-
- #region Internal Methods
-
- internal void RunPowerShellInActivityHost(System.Management.Automation.PowerShell powershell, PSDataCollection input,
- PSDataCollection output, PSActivityEnvironment policy, ConnectionAsyncResult asyncResult)
- {
- ActivityInvoker invoker =
- new ActivityInvoker
- {
- Input = input,
- Output = output,
- Policy = policy,
- PowerShell = powershell,
- AsyncResult = asyncResult
- };
-
- _requests.Enqueue(invoker);
- CheckAndStartServicingThread();
- }
-
- ///
- /// This is a helper method which should only be called
- /// from test code to reset stuff
- ///
- [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Justification = "This method is called from the tests")]
- internal void Reset()
- {
- foreach (ActivityHostProcess process in _hostProcesses)
- {
- process.Dispose();
- }
- _hostProcesses.Clear();
-
- InitializeActivityHostProcesses();
- }
-
- #endregion Internal Methods
-
- #region Constructors
-
- internal PSOutOfProcessActivityController(PSWorkflowRuntime runtime)
- : base(runtime)
- {
- if (runtime == null)
- throw new ArgumentNullException("runtime");
-
- Debug.Assert(runtime.Configuration != null, "For now only expecting PSWorkflowConfigurationProvider");
-
- this._configuration = runtime.Configuration;
- InitializeActivityHostProcesses();
- }
-
- #endregion Constructors
-
- #region Private Methods
-
- private void InitializeActivityHostProcesses()
- {
- // create the minimum number of hosts
- for (int i = 0; i < MinActivityHosts; i++)
- {
- ActivityHostProcess process = CreateNewActivityHostProcess();
- _hostProcesses.Add(process);
- }
- }
-
- private ActivityHostProcess CreateNewActivityHostProcess()
- {
- ActivityHostProcess process = new ActivityHostProcess(_configuration.ActivityProcessIdleTimeoutSec, _configuration.LanguageMode);
- process.ProcessCrashed += ProcessCrashed;
- process.Finished += ProcessFinished;
- process.OnProcessIdle += ProcessIdle;
-
- PerfCountersMgr.UpdateCounterByValue(
- PSWorkflowPerformanceCounterSetInfo.CounterSetId,
- PSWorkflowPerformanceCounterIds.ActivityHostMgrProcessesPoolSize);
- return process;
- }
-
- private void ProcessCrashed(object sender, ActivityHostCrashedEventArgs e)
- {
- // the process crashed, we need to not use it anymore
- ActivityHostProcess process = sender as ActivityHostProcess;
- Debug.Assert(process != null, "ActivityHostProcess did not raise event correctly");
- Debug.Assert(process.Busy, "When ProcessCrashed is raised busy should not be reset");
- process.MarkForRemoval = true;
-
- if (e.FailureOnSetup)
- {
- // the request needs to be processed again
- _failedRequests.Enqueue(e.Invoker);
- PerfCountersMgr.UpdateCounterByValue(
- PSWorkflowPerformanceCounterSetInfo.CounterSetId,
- PSWorkflowPerformanceCounterIds.ActivityHostMgrFailedRequestsPerSec);
- PerfCountersMgr.UpdateCounterByValue(
- PSWorkflowPerformanceCounterSetInfo.CounterSetId,
- PSWorkflowPerformanceCounterIds.ActivityHostMgrFailedRequestsQueueLength);
- }
-
- // Below call is added to fix the race condition:
- // When OOP host process is crashed, ProcessCrashed() method sets the process as MarkForRemoval, context switch happened at this time
- // and another process has finished and started the servicing thread, which checks the above process as MarkForRemoval and disposes it.
- // ProcessFinished event handler is unregistered from the process and ActivityHostProcess.HandleTransportError will not be able to raise
- // process finished event, resulting inconsistent _busyHost count.
- //
- DecrementHostCountAndStartThreads();
- }
-
- private void ProcessFinished(object sender, EventArgs e)
- {
- DecrementHostCountAndStartThreads();
- }
-
- private void DecrementHostCountAndStartThreads()
- {
- Interlocked.Decrement(ref _busyHosts);
-
- PerfCountersMgr.UpdateCounterByValue(
- PSWorkflowPerformanceCounterSetInfo.CounterSetId,
- PSWorkflowPerformanceCounterIds.ActivityHostMgrBusyProcessesCount,
- -1);
-
- CheckAndStartServicingThread();
- }
-
- private void ProcessIdle(object sender, EventArgs e)
- {
- // Only service thread should access the hostProcess collection
- // Start servicing thread if it is not running already
- //
- CheckAndStartServicingThread();
- }
-
- ///
- /// Handler method which runs a specific command in the specified process
- ///
- ///
- private static void RunPowerShellInActivityHostWorker(object state)
- {
- // Tuple object with HostProcess and ActivityInvoker is added to ThreadPool.QueueUserWorkItem as part of RunInProcess()
- // Back reference on ActivityHostProcess in ActivityInvoker is removed
- //
- Tuple tupleProcessAndInvoker = state as Tuple;
- tupleProcessAndInvoker.Item1.PrepareAndRun(tupleProcessAndInvoker.Item2);
- }
-
- ///
- /// Checks to see if a thread is servicing requests. If not
- /// starts one
- ///
- private void CheckAndStartServicingThread()
- {
- if (Interlocked.CompareExchange(ref _isServicing, Servicing, NotServicing) == NotServicing)
- {
- ThreadPool.QueueUserWorkItem(ServiceRequests);
- }
- }
-
- ///
- /// Method which performs the actual servicing of requests
- ///
- ///
- private void ServiceRequests(object state)
- {
- bool isFailedRequest = false;
- while (Interlocked.CompareExchange(ref _busyHosts, _configuration.MaxActivityProcesses, _configuration.MaxActivityProcesses) < _configuration.MaxActivityProcesses)
- {
- // if there are any processes marked for removal
- // remove them
- List toRemove = _hostProcesses.Where(process => process.MarkForRemoval).ToList();
-
- foreach(var process in toRemove)
- {
- SafelyDisposeProcess(process);
- }
-
- ActivityInvoker invoker;
- // first service previously failed request
- // and then a queued request
- if (_failedRequests.Count > 0)
- {
- _failedRequests.TryDequeue(out invoker);
- isFailedRequest = true;
- }
- else
- {
- _requests.TryDequeue(out invoker);
- isFailedRequest = false;
- }
-
- if (invoker == null) break;
-
- if (invoker.IsCancelled) continue;
-
- if (isFailedRequest)
- {
- PerfCountersMgr.UpdateCounterByValue(
- PSWorkflowPerformanceCounterSetInfo.CounterSetId,
- PSWorkflowPerformanceCounterIds.ActivityHostMgrFailedRequestsQueueLength,
- -1);
- }
- else
- {
- PerfCountersMgr.UpdateCounterByValue(
- PSWorkflowPerformanceCounterSetInfo.CounterSetId,
- PSWorkflowPerformanceCounterIds.ActivityHostMgrPendingRequestsQueueLength,
- -1);
- }
-
- bool processed = false;
- foreach (ActivityHostProcess process in _hostProcesses.Where(process => !process.Busy))
- {
- // we have found the first free process available use it
- processed = true;
- RunInProcess(invoker, process);
- break;
- }
-
- // if there weren't enough processes, then we create one more
- if (processed) continue;
-
- ActivityHostProcess hostProcess = CreateNewActivityHostProcess();
- _hostProcesses.Add(hostProcess);
- RunInProcess(invoker, hostProcess);
- }
-
- // we are all done, set servicing to false
- Interlocked.CompareExchange(ref _isServicing, NotServicing, Servicing);
-
- // Try to start the servicing thread again if there are any pending requests and activity host processes are available.
- // This is required to fix the race condition between CheckAndStartServicingThread() and ServiceRequests() methods.
- //
- if((_failedRequests.Count > 0 || _requests.Count > 0) &&
- Interlocked.CompareExchange(ref _busyHosts, _configuration.MaxActivityProcesses, _configuration.MaxActivityProcesses) < _configuration.MaxActivityProcesses)
- {
- CheckAndStartServicingThread();
- }
- }
-
-
- ///
- /// Unregisters all wait handles and disposes a process
- ///
- ///
- private void SafelyDisposeProcess(ActivityHostProcess process)
- {
- process.Finished -= ProcessFinished;
- process.ProcessCrashed -= ProcessCrashed;
- process.OnProcessIdle -= ProcessIdle;
-
- process.Dispose();
-
- _hostProcesses.Remove(process);
-
- PerfCountersMgr.UpdateCounterByValue(
- PSWorkflowPerformanceCounterSetInfo.CounterSetId,
- PSWorkflowPerformanceCounterIds.ActivityHostMgrProcessesPoolSize,
- -1);
- }
-
- ///
- /// Method called by servicing thread. This method will run the command in the
- /// specified process on a separate thread
- ///
- ///
- ///
- private void RunInProcess(ActivityInvoker invoker, ActivityHostProcess process)
- {
- if (invoker.IsCancelled)
- {
- return;
- }
-
- process.Busy = true;
- Interlocked.Increment(ref _busyHosts);
- PerfCountersMgr.UpdateCounterByValue(
- PSWorkflowPerformanceCounterSetInfo.CounterSetId,
- PSWorkflowPerformanceCounterIds.ActivityHostMgrBusyProcessesCount);
-
- // Adding Tuple object with HostProcess and ActivityInvoker to ThreadPool.QueueUserWorkItem
- // Back reference on ActivityHostProcess in ActivityInvoker is removed
- //
- Tuple tupleProcessAndInvoker = new Tuple(process, invoker);
- ThreadPool.QueueUserWorkItem(RunPowerShellInActivityHostWorker, tupleProcessAndInvoker);
- }
-
- #endregion Private Methods
-
- #region PSActivityHostManager Overrides
-
- ///
- /// Begin invocation of command specified in activity
- ///
- /// pipeline of command to execute
- /// input collection
- /// output collection
- /// policy to use for the activity
- /// optional callback
- /// optional caller specified state
- /// IAsyncResult
- internal IAsyncResult BeginInvokePowerShell(System.Management.Automation.PowerShell command,
- PSDataCollection input, PSDataCollection output, PSActivityEnvironment policy,
- AsyncCallback callback, object state)
- {
- if (command == null)
- {
- throw new ArgumentNullException("command");
- }
-
- ConnectionAsyncResult result = new ConnectionAsyncResult(state, callback, command.InstanceId);
-
- _structuredTracer.OutOfProcessRunspaceStarted(command.ToString());
-
- ActivityInvoker invoker =
- new ActivityInvoker
- {
- Input = input,
- Output = output,
- Policy = policy,
- PowerShell = command,
- AsyncResult = result
- };
-
- result.Invoker = invoker;
-
- _requests.Enqueue(invoker);
- PerfCountersMgr.UpdateCounterByValue(
- PSWorkflowPerformanceCounterSetInfo.CounterSetId,
- PSWorkflowPerformanceCounterIds.ActivityHostMgrIncomingRequestsPerSec);
- PerfCountersMgr.UpdateCounterByValue(
- PSWorkflowPerformanceCounterSetInfo.CounterSetId,
- PSWorkflowPerformanceCounterIds.ActivityHostMgrPendingRequestsQueueLength);
- CheckAndStartServicingThread();
- return result;
- }
-
- ///
- /// Block until operation is complete on the current thread
- ///
- /// IAsyncResult to block on
- internal void EndInvokePowerShell(IAsyncResult asyncResult)
- {
- ConnectionAsyncResult result = asyncResult as ConnectionAsyncResult;
-
- if (result == null)
- {
- throw new PSInvalidOperationException(Resources.AsyncResultNotValid);
- }
-
- result.EndInvoke();
- }
-
- ///
- /// Cancels an already started execution
- ///
- /// async result to cancel
- internal void CancelInvokePowerShell(IAsyncResult asyncResult)
- {
- ConnectionAsyncResult result = asyncResult as ConnectionAsyncResult;
- if (result != null)
- {
- result.Invoker.StopPowerShell();
- }
- }
-
- #endregion PSActivityHostManager Overrides
- }
-
- #region ActivityInvoker
-
- internal class ActivityInvoker
- {
- internal PSDataCollection Input { get; set; }
- internal PSDataCollection Output { get; set; }
- internal System.Management.Automation.PowerShell PowerShell { get; set; }
- internal PSActivityEnvironment Policy { get; set; }
- internal ConnectionAsyncResult AsyncResult { get; set; }
- private readonly object _syncObject = new object();
- private bool _invoked;
- private bool _cancelled;
- private readonly PowerShellTraceSource _tracer = PowerShellTraceSourceFactory.GetTraceSource();
-
- internal void InvokePowerShell(Runspace runspace)
- {
- IAsyncResult result = null;
-
- if (_cancelled)
- return;
-
- Exception invokeException = null;
-
- try
- {
- // Acquiring sync object to fix a race condition between BeginInvoke() and Stop() operations on powershell object.
- // Invoked flag is set only when begin invoke is succeeded, so that if this activity is cancelled, powershell needs to be stopped in StopPowerShell().
- //
- lock (_syncObject)
- {
- if (_cancelled)
- return;
-
- _tracer.WriteMessage("State of runspace passed to invoker ", runspace.RunspaceStateInfo.State.ToString());
-
- // at this point we assume we have a clean runspace to
- // run the command
- // if the runspace is broken then the invocation will
- // result in an error either ways
- PowerShell.Runspace = runspace;
-
- // Temporary fix:
- // If we are about to run this out of proc, we need to complete any open
- // input. Otherwise, the out-of-proc PowerShell will hang expecting input.
- // However, this has a bug that it will break a third command trying to
- // use the same input collection. Nana to resolve with final fix.
- if ((Input != null) && Input.EnumeratorNeverBlocks && Input.IsOpen)
- {
- Input.Complete();
- }
-
- _tracer.WriteMessage("BEGIN invocation of command out of proc");
- result = Output == null
- ? PowerShell.BeginInvoke(Input)
- : PowerShell.BeginInvoke(Input, Output);
-
- // _invoked should bet set here as powershell object can be disposed before runspace assignment due to cancelling an activity
- //
- _invoked = true;
- } // end of lock
-
- // wait until PowerShell Execution Completes
- PowerShell.EndInvoke(result);
- _tracer.WriteMessage("END invocation of command out of proc");
- }
- catch (Exception exception)
- {
- // Since the callback is internally handled there should
- // not be any exceptions. Fix the same
- // ignore any exceptions caused in the callback invocation
- _tracer.WriteMessage("Running powershell in activity host threw exception");
- _tracer.TraceException(exception);
- invokeException = exception;
-
- // transport errors are centrally handled for queue and process management
- if (exception is PSRemotingTransportException) throw;
- }
- finally
- {
- AsyncResult.SetAsCompleted(invokeException);
- }
- }
-
- internal void StopPowerShell()
- {
- bool needToStop = false;
-
- lock (_syncObject)
- {
- _cancelled = true;
-
- if (_invoked)
- {
- needToStop = true;
- }
- }
-
- if (needToStop)
- {
- PowerShell.Stop();
- }
-
- AsyncResult.SetAsCompleted(null);
- }
-
- internal bool IsCancelled
- {
- get
- {
- lock (_syncObject)
- {
- return _cancelled;
- }
- }
- }
- }
-
- #endregion ActivityInvoker
-
-}
diff --git a/src/Microsoft.PowerShell.Workflow.ServiceCore/ServiceCore/WorkflowCore/ActivityHostProcess.cs b/src/Microsoft.PowerShell.Workflow.ServiceCore/ServiceCore/WorkflowCore/ActivityHostProcess.cs
deleted file mode 100644
index 83ab8a5433..0000000000
--- a/src/Microsoft.PowerShell.Workflow.ServiceCore/ServiceCore/WorkflowCore/ActivityHostProcess.cs
+++ /dev/null
@@ -1,564 +0,0 @@
-/********************************************************************++
-Copyright (c) Microsoft Corporation. All rights reserved.
---********************************************************************/
-
-using System;
-using System.Collections.Generic;
-using System.Collections.ObjectModel;
-using System.Diagnostics;
-using System.Linq;
-using System.Management.Automation;
-using System.Management.Automation.Runspaces;
-using System.Management.Automation.Remoting;
-using System.Management.Automation.Tracing;
-using System.Management.Automation.PerformanceData;
-using System.Timers;
-using Timer = System.Timers.Timer;
-using System.Globalization;
-
-namespace Microsoft.PowerShell.Workflow
-{
- internal class ActivityHostCrashedEventArgs : EventArgs
- {
- internal bool FailureOnSetup { get; set; }
- internal ActivityInvoker Invoker { get; set; }
- }
-
- ///
- /// Encapsulates an out of process activity host
- ///
- /// This class is not thread safe. Caller has to
- /// ensure thread safety of accessing internal properties
- internal class ActivityHostProcess : IDisposable
- {
- #region Private Members
- private static PSPerfCountersMgr _perfCountersMgr = PSPerfCountersMgr.Instance;
- private Runspace _runspace;
- private static readonly WSManConnectionInfo ActivityHostConnectionInfo;
- private const string ActivityHostShellUri = "http://schemas.microsoft.com/powershell/Microsoft.PowerShell.Workflow.ActivityHost";
- private static readonly string[] ActivitiesTypesFiles = new[] {
- @"%windir%\system32\windowspowershell\v1.0\modules\psworkflow\PSWorkflow.types.ps1xml"
- };
- private static readonly TypeTable ActivitiesTypeTable;
- private const int WSManLocalPort = 47001;
- private bool _busy;
- private readonly object _syncObject = new object();
- private readonly PowerShellProcessInstance _processInstance;
- private readonly PowerShellTraceSource _tracer = PowerShellTraceSourceFactory.GetTraceSource();
- private ActivityInvoker _currentInvoker;
-
- ///
- /// This the period of time for which the process will
- /// remain inactive. Afterwards it will be killed
- ///
- private const int TimeOut = 5*60*1000;
- private readonly Timer _timer;
-
- ///
- /// Use this flag to flip between IPC process and
- /// WSMan process in localhost
- ///
- private readonly bool _useJobIPCProcess;
-
- private readonly PSLanguageMode? _languageMode;
-
- ///
- /// Creating a _PSSetVariable to set multiple variables in a single call --> PERF
- /// Naming it _PSSetVariable to avoid name collision with Set-Variable cmdlet
- ///
- private const string SetVariableFunction = @"function _PSSetVariable
- {
- [CmdletBinding()]
- param(
-
- [Parameter(Position=0)]
- [string[]]
- $Name,
-
- [Parameter(Position=1)]
- [object[]]
- $Value
- )
-
- for($i=0; $i -lt $Name.Count; $i++)
- {
- microsoft.powershell.utility\set-variable -name $Name[$i] -value $Value[$i] -scope global
- }
-
- Set-StrictMode -Off
- }";
-
- private bool _isDisposed;
- #endregion Private Members
-
- #region Constructors
-
- ///
- /// Initialize a connection info object in the static constructor
- /// It can be reused for all connections
- ///
- static ActivityHostProcess()
- {
- ActivityHostConnectionInfo = new WSManConnectionInfo { Port = WSManLocalPort, ShellUri = ActivityHostShellUri };
-
- List typefiles = TypeTable.GetDefaultTypeFiles();
- typefiles.AddRange(ActivitiesTypesFiles.Select(Environment.ExpandEnvironmentVariables));
- ActivitiesTypeTable = new TypeTable(typefiles);
-
- }
-
- internal ActivityHostProcess(int activityHostTimeoutSec, PSLanguageMode? languageMode)
- {
- _languageMode = languageMode;
- _useJobIPCProcess = true;
- _tracer.WriteMessage("BEGIN Creating new PowerShell process instance");
- _processInstance = new PowerShellProcessInstance();
- _tracer.WriteMessage("END Creating new PowerShell process instance ");
- _runspace = CreateRunspace();
- _tracer.WriteMessage("New runspace created ", _runspace.InstanceId.ToString());
- _timer = new Timer {AutoReset = false, Interval = TimeOut};
- _timer.Elapsed += TimerElapsed;
- _timer.Interval = activityHostTimeoutSec > 0 ? activityHostTimeoutSec*1000 : TimeOut;
- _perfCountersMgr.UpdateCounterByValue(
- PSWorkflowPerformanceCounterSetInfo.CounterSetId,
- PSWorkflowPerformanceCounterIds.ActivityHostMgrCreatedProcessesCount);
- }
-
- #endregion Constructors
-
- #region Private Methods
-
- ///
- /// Get the runspace corresponding to this process
- ///
- /// indicates if a new runspace
- /// needs to be created
- /// runspace object
- private Runspace GetRunspace(bool createNew)
- {
- if (_runspace.RunspaceStateInfo.State == RunspaceState.BeforeOpen)
- {
- // if the runspace is not opened, open it and return
- OpenRunspace(_runspace);
- }
- else
- {
- if (_useJobIPCProcess)
- {
- // dispose the existing runspace and create a new one
- CloseAndDisposeRunspace();
-
- _runspace = CreateRunspace();
- _tracer.WriteMessage("New runspace created ", _runspace.InstanceId.ToString());
- OpenRunspace(_runspace);
- }
- }
- return _runspace;
- }
-
- private void CloseAndDisposeRunspace()
- {
- try
- {
- // Close and dispose the existing runspace
- //
- _runspace.Close();
- _runspace.Dispose();
- }
- catch (Exception e)
- {
- // RemoteRunspace.Close can throw exceptions when Server process has exited or runspace is invalid.
- // Ignoring all exceptions as this runspace was used for previous OOP activity execution.
- //
- _tracer.TraceException(e);
-
- // do nothing
- }
- }
-
- ///
- /// Depending on the option return an Out-of-proc
- /// or remoting runspace on localhost
- ///
- /// runspace object for use
- private Runspace CreateRunspace()
- {
- return _useJobIPCProcess ? RunspaceFactory.CreateOutOfProcessRunspace(ActivitiesTypeTable, _processInstance) : RunspaceFactory.CreateRunspace(ActivityHostConnectionInfo, null, ActivitiesTypeTable);
- }
-
- ///
- /// Opens the specified runspace. If there are any errors in
- /// opening the runspace, the method just eats them so that
- /// an unhandled exception in the background thread in which this
- /// method is invoked does not lead to a process crash
- ///
- /// runspace to open
- private void OpenRunspace(Runspace runspace)
- {
- // a runspace open can fail for a variety of reasons
- // eat the exceptions
- try
- {
- _tracer.WriteMessage("Opening runspace " , _runspace.InstanceId.ToString());
- runspace.Open();
- _tracer.WriteMessage("Runspace opened successfully ", _runspace.InstanceId.ToString());
-
- if (_languageMode != null && _languageMode.HasValue)
- {
- using (System.Management.Automation.PowerShell ps = System.Management.Automation.PowerShell.Create())
- {
- ps.Runspace = runspace;
- string langScript = "$ExecutionContext.SessionState.LanguageMode = '" + _languageMode.Value.ToString() + "'";
- ps.AddScript(langScript);
- ps.Invoke();
- }
- }
- }
- catch (PSRemotingTransportRedirectException)
- {
- // we should not be getting this exception
- // in the normal case
- _tracer.WriteMessage("Opening runspace threw PSRemotingTransportRedirectException", _runspace.InstanceId.ToString());
- Debug.Assert(false, "We should not get a redirect exception under normal circumstances");
- }
- catch (PSRemotingTransportException transportException)
- {
- _tracer.WriteMessage("Opening runspace threw PSRemotingTransportException", _runspace.InstanceId.ToString());
- _tracer.TraceException(transportException);
- // throwing PSRemotingTransportException exception as it will be handled at single place in PrepareAndRun() method.
- throw;
- }
- catch(PSRemotingDataStructureException)
- {
- // just eat the exception
- _tracer.WriteMessage("Opening runspace threw PSRemotingDataStructureException", _runspace.InstanceId.ToString());
- Debug.Assert(false, "We should not get a protocol exception under normal circumstances");
- }
- }
-
- ///
- /// Import all the specified modules in the specified runspace
- ///
- /// runspace in which to import the modules
- /// collection of modules to import
- /// true if setting up of runspace from policy succeeded
- private void ImportModulesFromPolicy(Runspace runspace, ICollection modules)
- {
- // If any modules are specified, load them into the runspace.
- // In general, autoloading should be preferred to explicitly loading a module
- // at startup time...
- if (modules.Count <= 0)
- return;
-
- using (System.Management.Automation.PowerShell ps = System.Management.Automation.PowerShell.Create())
- {
- ps.Runspace = runspace;
- // Setting erroraction to stop for import-module since they are required modules. If not present, stop the execution
- ps.AddCommand("Import-Module").AddArgument(modules).AddParameter("ErrorAction",ActionPreference.Stop).AddParameter("Force");
- ps.Invoke();
- }
- }
-
- ///
- /// Set the specified variables in the runspace
- ///
- /// runspace in which the variables need
- /// to be set
- /// collection of variables that need to be set
- private void SetVariablesFromPolicy(Runspace runspace, IDictionary variables)
- {
- using (System.Management.Automation.PowerShell ps = System.Management.Automation.PowerShell.Create())
- {
- ps.Runspace = runspace;
- ps.AddScript(SetVariableFunction);
- ps.Invoke();
-
- ps.Commands.Clear();
- ps.AddCommand("_PSSetVariable").AddParameter("Name", variables.Keys).AddParameter("Value", variables.Values);
- ps.Invoke();
-
- // Remove the temporary function _PSSetVariable after its use is done.
- ps.Commands.Clear();
- ps.AddCommand("Remove-Item").AddParameter("Path", "function:\\_PSSetVariable").AddParameter("Force");
- ps.Invoke();
-
- }
- }
-
- ///
- /// Set the busy flag since the process is being used.
- /// Stop the idle timer
- ///
- private void SetBusy()
- {
- lock(_syncObject)
- {
- _busy = true;
-
- // stop the idle timer
- _timer.Stop();
- }
- }
-
- ///
- /// Reset the busy flag and start the idle timer
- ///
- private void ResetBusy()
- {
- lock(_syncObject)
- {
- // Process state should not be set to false if it is already marked for removal
- // Process is marked for removal in two cases:
- // 1) When PSRemotingTransportException is received in PrepareAndRun, in this case Server process is already crashed/exited.
- // If busy state is set to false, this process can be assigned to another activity by the servicing thread.
- // Instead of adding separate boolean variable in PrepareAndRun to call ResetBusy we are checking for not marked for removal here.
- // 2) When idle time of 5 min elapsed, process is marked for removal so that server process can be killed. After this, ResetBusy is never called.
- //
- if (_busy && !_markForRemoval)
- {
- _busy = false;
-
- // enable the idle timer
- _timer.Enabled = true;
-
- this.RaiseProcessFinishedEvent();
- }
- }
- }
-
- ///
- /// Idle timeout has occured. If the runspace is not being used
- /// just close it
- ///
- /// sender of this event
- /// unused
- private void TimerElapsed(object sender, ElapsedEventArgs e)
- {
- lock (_syncObject)
- {
- if (_busy) return;
-
- // Mark this process for removal and set it as busy so that this process will not be assigned to any new activity.
- // Marking for removal will ensure that servicing thread will remove this object from host process collection.
- //
- _busy = true;
- _markForRemoval = true;
- }
-
- if (OnProcessIdle != null)
- OnProcessIdle(this, new EventArgs());
- }
-
- ///
- /// Handles a transport error since it is most likely that
- /// the process crash
- ///
- /// the transport exception
- /// that was raised
- /// true indicates that the crash was
- /// encountered when setting up the process and not when the
- /// command was run
- private void HandleTransportError(PSRemotingTransportException transportException, bool onSetup)
- {
- _tracer.TraceException(transportException);
-
- if (ProcessCrashed != null)
- {
- ActivityHostCrashedEventArgs eventArgs = new ActivityHostCrashedEventArgs
- {FailureOnSetup = onSetup,
- Invoker = _currentInvoker};
- ProcessCrashed(this, eventArgs);
- }
- }
-
- internal void RaiseProcessFinishedEvent()
- {
- if (Finished != null)
- Finished(this, new EventArgs());
- }
-
- #endregion Private Methods
-
- #region Internal Methods
-
- internal static String ActivityHostConfiguration
- {
- get { return ActivityHostShellUri; }
- }
- internal event EventHandler Finished;
- internal event EventHandler OnProcessIdle;
-
- internal event EventHandler ProcessCrashed;
-
- ///
- /// Prepare the environment based on the policy and run the powershell
- ///
- ///
- /// It is assumed that the caller of this method will spawn appropriate
- /// thread and so it is fine for us to call the callback on the same thread
- internal void PrepareAndRun(ActivityInvoker invoker)
- {
- bool setupSucceeded = false;
- try
- {
- // Transport (PSRemotingTransportException) error can happen during setup/prepare phase, so it is getting assigned before setup phase.
- //
- _currentInvoker = invoker;
- Runspace runspace = null;
- // Retry for 10 times if runspace is in Broken state
- //
- // Runspace can be broken, when a remote runspace is getting closed during the next activity execution,
- // the close ack is getting timedout and that close ack is received by the newly created remote runspace for
- // the next activity since stdoutput stream of server process is not cleared/discarded,
- // that is why during new runspace is in broken state while it is being opened.
- //
- for (int i = 1; (i <= 10) && !invoker.IsCancelled; i++)
- {
- // prepare the runspace with the necessary
- // modules and variables here
- runspace = GetRunspace(true);
-
- if (runspace.RunspaceStateInfo.State == RunspaceState.Opened)
- break;
-
- System.Threading.Thread.Sleep(i*200);
- }
-
- if (invoker.IsCancelled)
- {
- return;
- }
-
- Debug.Assert((runspace.RunspaceStateInfo.State == RunspaceState.Opened), "Runspace is not in Opened state for running an OOP activity");
-
- if (invoker.Policy.Variables.Count > 0)
- {
- // set the variables in the specified runspace
- _tracer.WriteMessage("BEGIN Setting up variables in runspace ", _runspace.InstanceId.ToString());
- SetVariablesFromPolicy(runspace, invoker.Policy.Variables);
- _tracer.WriteMessage("END Setting up variables in runspace ", _runspace.InstanceId.ToString());
- }
-
- if (invoker.Policy.Modules.Count > 0)
- {
- // attempt loading the modules in the specified runspace
- _tracer.WriteMessage("BEGIN Setting up runspace from policy ", _runspace.InstanceId.ToString());
- ImportModulesFromPolicy(runspace, invoker.Policy.Modules);
- _tracer.WriteMessage("END Setting up runspace from policy ", _runspace.InstanceId.ToString());
- }
-
- // Prepare phase is completed without any issues.
- // setupSucceeded flag is used in HandleTransportError method to enqueue the current activity for retry.
- // If there is any PSRemotingTransportException during InvokePowershell current activity will not be enqueued to setup failed requests in ActivityHostManager.
- //
- setupSucceeded = true;
-
- // at this point we assume we have a clean runspace to
- // run the command
- // if the runspace is broken then the invocation will
- // result in an error either ways
- invoker.InvokePowerShell(runspace);
- }
- catch (PSRemotingTransportException transportException)
- {
- HandleTransportError(transportException, !setupSucceeded);
- }
- catch (Exception e)
- {
- // at this point there is an exception other than a
- // transport exception that is caused by trying to
- // setup the runspace. Release the asyncresult
- // accordingly
- _tracer.TraceException(e);
- invoker.AsyncResult.SetAsCompleted(e);
- }
- finally
- {
- _currentInvoker = null;
- ResetBusy();
- }
- }
-
- ///
- /// If the process represented by this object is busy
- ///
- internal bool Busy
- {
- get
- {
- lock (_syncObject)
- {
- return _busy;
- }
- }
- set
- {
- if (value) SetBusy();
- else ResetBusy();
- }
- }
-
- ///
- /// Indicates that the associated process crashed and this object
- /// needs to be removed by ActivityHostManager
- ///
- internal bool MarkForRemoval {
- get
- {
- // _processInstance.HasExited can not be used to tell as marked for removal
- // as it will cause inconsistent busy host count
- //
- return _markForRemoval;
- }
- set
- {
- _markForRemoval = value;
- }
- }
- private bool _markForRemoval = false;
-
- #endregion Internal Methods
-
- #region IDisposable
-
- ///
- /// Dispose
- ///
- public void Dispose()
- {
- Dispose(true);
- GC.SuppressFinalize(this);
- }
-
- ///
- /// dispose of managed resources
- ///
- /// true if being disposed
- protected void Dispose(bool disposing)
- {
- if (!disposing) return;
-
- if (_isDisposed) return;
- lock (_syncObject)
- {
- if (_isDisposed) return;
- _isDisposed = true;
- }
-
- Debug.Assert(_runspace != null, "Runspace is already null");
-
- CloseAndDisposeRunspace();
-
- _processInstance.Dispose();
-
- _currentInvoker = null;
- _tracer.Dispose();
-
- _perfCountersMgr.UpdateCounterByValue(
- PSWorkflowPerformanceCounterSetInfo.CounterSetId,
- PSWorkflowPerformanceCounterIds.ActivityHostMgrDisposedProcessesCount);
- }
-
- #endregion IDisposable
- }
-}
diff --git a/src/Microsoft.PowerShell.Workflow.ServiceCore/ServiceCore/WorkflowCore/ActivityUtils.cs b/src/Microsoft.PowerShell.Workflow.ServiceCore/ServiceCore/WorkflowCore/ActivityUtils.cs
deleted file mode 100644
index ccc5af3344..0000000000
--- a/src/Microsoft.PowerShell.Workflow.ServiceCore/ServiceCore/WorkflowCore/ActivityUtils.cs
+++ /dev/null
@@ -1,116 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Management.Automation;
-using System.Management.Automation.Remoting;
-using System.Management.Automation.Runspaces;
-using Microsoft.PowerShell.Workflow;
-
-namespace Microsoft.PowerShell.Activities
-{
- static class ActivityUtils
- {
- // Extension method to add IsNullOrEmpty to arrays.
- internal static bool IsNullOrEmpty(this System.Collections.ICollection c)
- {
- return (c == null || c.Count == 0);
- }
-
- private static int DefaultMaximumConnectionRedirectionCount = 5;
-
- internal static List GetConnectionInfo(string[] PSComputerName, string[] PSConnectionUri,
- string PSCertificateThumbprint, string PSConfigurationName,
- bool? PSUseSsl, uint? PSPort, string PSApplicationName,
- PSCredential PSCredential, AuthenticationMechanism PSAuthentication,
- bool PSAllowRedirection, System.Management.Automation.Remoting.PSSessionOption options)
- {
- List connections = new List();
-
- string[] machineList = null;
- bool connectByComputerName = false;
-
- // Connect by computername
- if ((! PSComputerName.IsNullOrEmpty()) && (PSConnectionUri.IsNullOrEmpty()))
- {
- machineList = PSComputerName;
- connectByComputerName = true;
- }
- else if ((PSComputerName.IsNullOrEmpty()) && (! PSConnectionUri.IsNullOrEmpty()))
- {
- machineList = PSConnectionUri;
- }
- else
- {
- throw new ArgumentException(Resources.CannotSupplyUriAndComputername);
- }
-
- // Go through each machine in the list an update its properties
- foreach (string machine in machineList)
- {
- if (!string.IsNullOrEmpty(machine))
- {
- WSManConnectionInfo connectionInfo = new WSManConnectionInfo();
-
- if (PSPort.HasValue)
- {
- connectionInfo.Port = (int)PSPort.Value;
- }
-
- if (PSUseSsl.HasValue && (PSUseSsl.Value))
- {
- connectionInfo.Scheme = WSManConnectionInfo.HttpsScheme;
- }
-
- if (!String.IsNullOrEmpty(PSConfigurationName))
- {
- connectionInfo.ShellUri = PSConfigurationName;
- }
-
- if (!String.IsNullOrEmpty(PSApplicationName))
- {
- connectionInfo.AppName = PSApplicationName;
- }
-
- if (connectByComputerName)
- {
- connectionInfo.ComputerName = machine;
- }
- else
- {
- connectionInfo.ConnectionUri = (Uri)LanguagePrimitives.ConvertTo(machine, typeof(Uri), System.Globalization.CultureInfo.InvariantCulture);
- }
-
- if (PSCredential != null)
- {
- connectionInfo.Credential = PSCredential;
- }
-
- if (!String.IsNullOrEmpty(PSCertificateThumbprint))
- {
- connectionInfo.CertificateThumbprint = PSCertificateThumbprint;
- }
-
- if (PSAuthentication != AuthenticationMechanism.Default)
- {
- connectionInfo.AuthenticationMechanism = PSAuthentication;
- }
-
- connectionInfo.MaximumConnectionRedirectionCount = PSAllowRedirection ? DefaultMaximumConnectionRedirectionCount : 0;
-
- if (options != null)
- {
- connectionInfo.SetSessionOptions(options);
- }
-
- connections.Add(connectionInfo);
- }
- else
- {
- // add a null connection to account for "" or $null in PSComputerName parameter
- connections.Add(null);
- }
- }
-
- return connections;
- }
- }
-}
\ No newline at end of file
diff --git a/src/Microsoft.PowerShell.Workflow.ServiceCore/ServiceCore/WorkflowCore/ConnectionManager.cs b/src/Microsoft.PowerShell.Workflow.ServiceCore/ServiceCore/WorkflowCore/ConnectionManager.cs
deleted file mode 100644
index 93404b4c62..0000000000
--- a/src/Microsoft.PowerShell.Workflow.ServiceCore/ServiceCore/WorkflowCore/ConnectionManager.cs
+++ /dev/null
@@ -1,2372 +0,0 @@
-/*
- * Copyright (c) 2010 Microsoft Corporation. All rights reserved
- */
-using System;
-using System.Collections;
-using System.Collections.Concurrent;
-using System.Collections.Generic;
-using System.Collections.ObjectModel;
-using System.Diagnostics;
-using System.Globalization;
-using System.Linq;
-using System.Management.Automation;
-using System.Management.Automation.Runspaces;
-using System.Threading;
-using System.Timers;
-using Timer = System.Timers.Timer;
-using Microsoft.PowerShell.Activities;
-using System.Management.Automation.Tracing;
-using System.Management.Automation.PerformanceData;
-
-namespace Microsoft.PowerShell.Workflow
-{
- #region Connection
-
- ///
- /// class the contains a remote connection (runspace) and associated
- /// data for managing the same
- ///
- /// the only reason this class has an internal scope is for
- /// test purposes. Else this can be a private class inside
- /// connection manager
- internal class Connection
- {
- private Runspace _runspace;
- private bool _busy;
- private bool _idle;
- private readonly object _syncObject = new object();
- private static readonly EventArgs EventArgs = new EventArgs();
- private readonly Guid _instanceId = Guid.NewGuid();
- private readonly PowerShellTraceSource _tracer = PowerShellTraceSourceFactory.GetTraceSource();
- private readonly Tracer _structuredTracer = new Tracer();
- private static readonly PSPerfCountersMgr _perfCountersMgr = PSPerfCountersMgr.Instance;
- private bool _readyForDisconnect = false;
- private bool _readyForReconnect = false;
- private ConnectionManager _manager;
-
- ///
- /// retry interval cannot be 0, so initial value is 1
- ///
- private uint _retryInterval = 1;
-
- internal uint RetryAttempt { get; set; }
- internal uint RetryCount { get; set; }
- internal GetRunspaceAsyncResult AsyncResult { get; set; }
- internal WSManConnectionInfo ConnectionInfo { get; set; }
-
- internal event EventHandler CloseCompleted;
- internal event EventHandler OpenCompleted;
- internal event EventHandler DisconnectCompleted;
- internal event EventHandler ReconnectCompleted;
-
- private const int Open = 1;
- private const int Close = 2;
- private const int Disconnect = 3;
- private const int Reconnect = 4;
-
- internal Connection(ConnectionManager manager)
- {
- _manager = manager;
- _tracer.WriteMessage("PSW Conn: Creating new connection");
- }
-
- internal bool DisconnectedIntentionally { get; set; }
-
- internal Runspace Runspace
- {
- get { return _runspace; }
- }
-
- internal Guid InstanceId
- {
- get { return _instanceId; }
- }
-
- internal bool Idle
- {
- get
- {
- lock (_syncObject)
- {
- return _idle;
- }
- }
- set
- {
- lock (_syncObject)
- {
- _idle = value;
- }
- }
- }
- internal bool ReadyForDisconnect
- {
- get
- {
- lock (_syncObject)
- {
- return _readyForDisconnect;
- }
- }
-
- set
- {
- lock (_syncObject)
- {
- _readyForDisconnect = value;
-
- if (_readyForDisconnect)
- _readyForReconnect = false;
- }
- }
- }
-
- internal bool ReadyForReconnect
- {
- get
- {
- lock (_syncObject)
- {
- return _readyForReconnect;
- }
- }
- set
- {
- lock (_syncObject)
- {
- _readyForReconnect = value;
-
- if (_readyForReconnect)
- _readyForDisconnect = false;
- }
- }
- }
-
- internal bool Busy
- {
- get
- {
- lock (_syncObject)
- {
- return _busy;
- }
- }
- set
- {
- lock (_syncObject)
- {
- _busy = value;
-
- if (_busy)
- {
- _idle = false;
- }
-
- // connection is set to busy by the connection manager
- // when it is assigning the connection to a new activity
- // then the connection should be marked as not ready for
- // disconnect since the activity has to signal the same
- // when it is not busy we do not want to disconnect idle
- // connections, hence it needs to be marked as not ready
- // for disconnect
- _readyForDisconnect = false;
- _readyForReconnect = false;
- }
- }
- }
-
- internal uint RetryInterval
- {
- get { return _retryInterval; }
- set
- {
- _retryInterval = value;
- if (_retryInterval == 0) _retryInterval = 1;
- }
- }
-
- private bool CheckAndReconnectAfterCrashOrShutdown(WSManConnectionInfo connectionInfo)
- {
- bool connectAsyncSucceeded = false;
-
- RunCommandsArguments args = this.AsyncResult.AsyncState as RunCommandsArguments;
- if (args != null)
- {
- Guid runspaceId = args.ImplementationContext.DisconnectedRunspaceInstanceId;
-
- ActivityImplementationContext implementationContext = args.ImplementationContext;
- System.Management.Automation.PowerShell currentPowerShellInstance = implementationContext.PowerShellInstance;
- PSActivityContext psActivityContext = args.PSActivityContext;
-
- // Non-empty guid represents that args.ImplementationContext.EnableRemotingActivityAutoResume is true
- if (!runspaceId.Equals(Guid.Empty))
- {
- Runspace[] runspaces = null;
-
- try
- {
- // Queries the server for disconnected runspaces.
- // Each runspace object in the returned array is in the Disconnected state and can be
- // connected to the server by calling the Connect() or ConnectAsync() methods on the runspace.
- runspaces = Runspace.GetRunspaces(connectionInfo);
- }
- catch (System.Management.Automation.RuntimeException)
- {
- _tracer.WriteMessage("PSW Conn: Disconnected Remote Runspace is not available. Runspace Instance Id: " + runspaceId.ToString());
- }
-
- if (runspaces != null)
- {
- // In local machine case, remote runspace with the specific id will be not be available after machine shutdown.
- // Remoterunspace on local machine may be available if only current process is crashed or suspended forcefully.
- // OpenAsync() will takes care of create new remote runspace if disconnected runspace is not available.
-
- Runspace foundRunspace = runspaces.FirstOrDefault(currentRunspace => currentRunspace.InstanceId.Equals(runspaceId));
-
- if (foundRunspace != null && foundRunspace.RunspaceStateInfo.State == RunspaceState.Disconnected)
- {
- System.Management.Automation.PowerShell disconnectedPowerShell = null;
-
- try
- {
- // When disconnectedPowerShell is not available PSInvalidOperationException will be thrown and finally block takes care of releasing the runspace.
- // And OpenAsync() will create a new remote runspace if disconnected runspace is not available.
- disconnectedPowerShell = foundRunspace.CreateDisconnectedPowerShell();
-
- // Add stream handler and connect to disconnected remote runspace
- PSActivity.AddHandlersToStreams(disconnectedPowerShell, args);
- disconnectedPowerShell.ConnectAsync(args.Output, PSActivity.PowerShellInvocationCallback, args);
-
-
- // Assign the disconnected powershell to ImplementationContext and dispose the existing powershell instance.
- implementationContext.PowerShellInstance = disconnectedPowerShell;
-
- // Since we are disposing the current command, remove this command from the list
- // of running commands.
- lock (psActivityContext.runningCommands)
- {
- RetryCount retryCount = psActivityContext.runningCommands[currentPowerShellInstance];
- psActivityContext.runningCommands.Remove(currentPowerShellInstance);
- psActivityContext.runningCommands[disconnectedPowerShell] = retryCount;
- }
- currentPowerShellInstance.Dispose();
-
- _runspace = foundRunspace;
- _runspace.StateChanged += RunspaceStateChanged;
-
- connectAsyncSucceeded = true;
- }
- catch (PSInvalidOperationException)
- {
- _tracer.WriteMessage("PSW Conn: Disconnected PowerShell is not available. Runspace Instance Id: " + foundRunspace.InstanceId.ToString());
- }
- finally
- {
- // release the runspace if reconnect did not happen.
- if (connectAsyncSucceeded == false && foundRunspace != null)
- {
- try
- {
- // Remove stream handlers on disconnectedPowerShell
- // Non null disconnectedPowerShell represents that handlers were added on disconnectedPowerShell and an exception happened during ConnectAsync.
- if (disconnectedPowerShell != null)
- PSActivity.RemoveHandlersFromStreams(disconnectedPowerShell, args);
-
- foundRunspace.Close();
- foundRunspace.Dispose();
- }
- catch (Exception)
- {
- // Runspace.Close can throw exceptions when Server process has exited or runspace is invalid.
- // Ignoring all exceptions.
- //
- _tracer.WriteMessage("PSW Conn: Disconnected PowerShell is not available. Runspace Instance Id: " + foundRunspace.InstanceId.ToString());
- }
- }
- }
- }
- }
- }
- }
-
- return connectAsyncSucceeded;
- }
-
- internal void OpenAsync()
- {
- // Always create runspace with WSManConnectionInfo.EnableNetworkAccess set to true.
- WSManConnectionInfo copyConnectionInfo = ConnectionInfo.Copy();
- copyConnectionInfo.EnableNetworkAccess = true;
-
- // If the remote runspace is not available after crash/shutdown,
- // activity task resume will fall back to reexecuting in a new runspace is assigned for the connection
- if (!CheckAndReconnectAfterCrashOrShutdown(copyConnectionInfo))
- {
- _runspace = RunspaceFactory.CreateRunspace(copyConnectionInfo, null, LocalRunspaceProvider.SharedTypeTable);
- _runspace.StateChanged += RunspaceStateChanged;
- _tracer.WriteMessage("PSW Conn: Calling OpenAsync on runspace");
- _runspace.OpenAsync();
- }
- }
-
- internal void CloseAsync()
- {
- _tracer.WriteMessage("PSW Conn: Calling CloseAsync on runspace");
-
- // at this point the runspace can be in a closed or broken state
- // if so then close has to simply raise the event
- // if it was not in a terminal state when checking but happens
- // later but before CloseAsync() is called then the other
- // call which caused the state change will raise an event
- if (_runspace.RunspaceStateInfo.State == RunspaceState.Broken ||
- _runspace.RunspaceStateInfo.State == RunspaceState.Closed)
- {
- RaiseEvents(Close);
- }
- else
- _runspace.CloseAsync();
- }
-
- internal void DisconnectAsync()
- {
- bool disconnect = false;
-
- if (_readyForDisconnect)
- {
- lock (_syncObject)
- {
- if (_readyForDisconnect)
- {
- _readyForDisconnect=false;
- _readyForReconnect = false;
- disconnect = true;
- }
- }
- if (disconnect)
- {
- _tracer.WriteMessage("PSW Conn: Calling Disconnect Async");
- _manager.DisconnectCalled();
- _runspace.DisconnectAsync();
- return;
- }
- }
- RaiseEvents(Disconnect);
- }
-
- internal void ReconnectAsync()
- {
- bool reconnect = false;
-
- if (_readyForReconnect)
- {
- lock (_syncObject)
- {
- if (_readyForReconnect)
- {
- _readyForReconnect = false;
- _readyForDisconnect = false;
- reconnect = true;
- }
- }
-
- if (reconnect)
- {
- _tracer.WriteMessage("PSW Conn: Calling reconnect async");
- _manager.ReconnectCalled();
- _runspace.ConnectAsync();
- return;
- }
- }
- RaiseEvents(Reconnect);
- }
-
- private void RunspaceStateChanged(object sender, RunspaceStateEventArgs e)
- {
- _structuredTracer.RunspaceStateChanged(this._instanceId.ToString(), e.RunspaceStateInfo.State.ToString(), string.Empty);
- _tracer.WriteMessage("PSW Conn: runspace state" + e.RunspaceStateInfo.State.ToString());
- switch (e.RunspaceStateInfo.State)
- {
- case RunspaceState.Opening:
- return;
-
- case RunspaceState.Closing:
- return;
-
- case RunspaceState.Disconnecting:
- {
- ReadyForDisconnect = false;
- }
- return;
-
- case RunspaceState.Opened:
- {
- // runspace opened successfully, assign it to the asyncresult
- // reset retry counter
- RetryAttempt = 0;
- ReadyForReconnect = false;
- AsyncResult.Connection = this;
- // this SetAsCompleted will result in the callback to the
- // activity happening in the WinRM thread
- AsyncResult.SetAsCompleted(null);
- RaiseEvents(Open);
- RaiseEvents(Reconnect);
- }
- break;
-
- case RunspaceState.Broken:
- {
- // Dispose the broken runspace before retry
- DisposeRunspace();
-
- // connection attempt failed, retry
- if (RetryCount > 0 && RetryAttempt < RetryCount)
- {
- RetryAttempt++;
-
- LogRetryAttempt(RetryAttempt, RetryCount);
-
- Timer timer = new Timer { AutoReset = false, Enabled = false, Interval = _retryInterval * 1000 };
- timer.Elapsed += RetryTimerElapsed;
- timer.Start();
- }
- else
- {
- // all retries have failed, end the asyncresult with an exception
- // message
- Busy = false;
-
- lock (_syncObject)
- {
- if (AsyncResult != null)
- {
- AsyncResult.Connection = null;
- AsyncResult.SetAsCompleted(e.RunspaceStateInfo.Reason);
- }
- }
-
- _tracer.WriteMessage(String.Format(CultureInfo.InvariantCulture, "Disposing broken connection to {0}", _runspace.ConnectionInfo.ComputerName));
-
- RaiseEvents(Open);
- RaiseEvents(Disconnect);
- RaiseEvents(Close);
- RaiseEvents(Reconnect);
- }
- }
- break;
-
- case RunspaceState.Disconnected:
- {
- ReadyForReconnect = true;
- RaiseEvents(Disconnect);
- }
- break;
-
- case RunspaceState.Closed:
- {
- DisposeRunspace();
- RaiseEvents(Close);
- }
- break;
- }
- }
-
- private void LogRetryAttempt(uint retryAttempt, uint retryTotal)
- {
- RunCommandsArguments args = this.AsyncResult.AsyncState as RunCommandsArguments;
- if (args != null)
- {
- PSActivityContext psActivityContext = args.PSActivityContext;
-
- // Write / Log that an activity retry was required.
- if (psActivityContext.progress != null)
- {
- string progressActivity = ((System.Activities.Activity)psActivityContext.ActivityObject).DisplayName;
-
- if (string.IsNullOrEmpty(progressActivity))
- progressActivity = psActivityContext.ActivityType.Name;
-
- string retryMessage = String.Format(CultureInfo.CurrentCulture, Resources.RetryingConnection, retryAttempt, retryTotal);
-
- ProgressRecord progressRecord = new ProgressRecord(0, progressActivity, retryMessage);
- lock (psActivityContext.progress)
- {
- psActivityContext.progress.Add(progressRecord);
- }
- }
- }
- }
-
- private void RaiseEvents(int eventType)
- {
- switch (eventType)
- {
- case Open:
- {
- if (OpenCompleted != null) OpenCompleted(this, EventArgs);
- }
- break;
- case Close:
- {
- if (CloseCompleted != null) CloseCompleted(this, EventArgs);
- }
- break;
- case Disconnect:
- {
- if (DisconnectCompleted != null) DisconnectCompleted(this, EventArgs);
- }
- break;
- case Reconnect:
- {
- if (ReconnectCompleted != null) ReconnectCompleted(this, EventArgs);
- }
- break;
- }
- }
-
- private void DisposeRunspace()
- {
- _runspace.StateChanged -= RunspaceStateChanged;
- _tracer.WriteMessage("PSW Conn: disposing runspace");
- _runspace.Dispose();
- _perfCountersMgr.UpdateCounterByValue(
- PSWorkflowPerformanceCounterSetInfo.CounterSetId,
- PSWorkflowPerformanceCounterIds.PSRemotingConnectionsDisposedCount);
- }
-
- private void RetryTimerElapsed(object sender, ElapsedEventArgs elapsedEventArgs)
- {
- // specified retry interval timeout has elapsed, try again
- // dispose the timer
- Timer timer = sender as Timer;
- if (timer != null) timer.Dispose();
-
- // retry the connection again
- OpenAsync();
- }
- }
-
- #endregion Connection
-
- #region GetRunspaceAsyncResult
-
- ///
- /// AsyncResult object returned by ConnectionManager
- ///
- /// the only reason this class has an internal scope is for
- /// test purposes. Else this can be a private class inside
- /// connection manager
- internal class GetRunspaceAsyncResult : ConnectionAsyncResult
- {
- internal GetRunspaceAsyncResult(object state, AsyncCallback callback, Guid ownerId) :
- base(state, callback, ownerId)
- {
- }
-
- internal Connection Connection { get; set; }
- }
-
- #endregion GetRunspaceAsyncResult
-
- #region ThrottleOperation
-
- internal abstract class ThrottleOperation
- {
- internal event EventHandler OperationComplete;
- private static readonly EventArgs EventArgs = new EventArgs();
-
- internal void RaiseOperationComplete()
- {
- if (OperationComplete != null) OperationComplete(this, EventArgs);
- }
-
- internal virtual void DoOperation()
- {
- throw new NotImplementedException();
- }
- }
-
- internal class OpenOperation : ThrottleOperation
- {
- private readonly Connection _connection;
-
- internal OpenOperation(Connection connection)
- {
- _connection = connection;
- _connection.OpenCompleted += HandleOpenCompleted;
- }
-
- private void HandleOpenCompleted(object sender, EventArgs eventArgs)
- {
- _connection.OpenCompleted -= HandleOpenCompleted;
- RaiseOperationComplete();
- }
-
- internal override void DoOperation()
- {
- _connection.OpenAsync();
- }
- }
-
- internal class CloseOperation : ThrottleOperation
- {
- private readonly Connection _connection;
- internal Connection Connection
- {
- get { return _connection; }
- }
-
- internal CloseOperation(Connection connection)
- {
- _connection = connection;
- _connection.CloseCompleted += HandleCloseCompleted;
- }
-
- private void HandleCloseCompleted(object sender, EventArgs eventArgs)
- {
- _connection.CloseCompleted -= HandleCloseCompleted;
- RaiseOperationComplete();
- }
-
- internal override void DoOperation()
- {
- _connection.CloseAsync();
- }
- }
-
- internal class CloseOneAndOpenAnotherOperation : ThrottleOperation
- {
- private readonly Connection _connectionToClose;
- private readonly Connection _connectionToOpen;
-
- internal CloseOneAndOpenAnotherOperation(Connection toClose, Connection toOpen)
- {
- _connectionToClose = toClose;
- _connectionToOpen = toOpen;
-
- _connectionToClose.CloseCompleted += HandleCloseCompleted;
- _connectionToOpen.OpenCompleted += HandleOpenCompleted;
- }
-
- private void HandleOpenCompleted(object sender, EventArgs eventArgs)
- {
- _connectionToOpen.OpenCompleted -= HandleOpenCompleted;
- RaiseOperationComplete();
- }
-
- private void HandleCloseCompleted(object sender, EventArgs eventArgs)
- {
- _connectionToClose.CloseCompleted -= HandleCloseCompleted;
- _connectionToOpen.OpenAsync();
- }
-
- internal override void DoOperation()
- {
- _connectionToClose.CloseAsync();
- }
- }
-
- internal class DisconnectOperation : ThrottleOperation
- {
- private readonly Connection _connection;
-
- internal DisconnectOperation(Connection connection)
- {
- _connection = connection;
- _connection.DisconnectCompleted += HandleDisconnectCompleted;
- }
-
- private void HandleDisconnectCompleted(object sender, EventArgs eventArgs)
- {
- _connection.DisconnectCompleted -= HandleDisconnectCompleted;
- RaiseOperationComplete();
- }
-
- internal override void DoOperation()
- {
- _connection.DisconnectAsync();
- }
- }
-
- internal class ReconnectOperation : ThrottleOperation
- {
- private readonly Connection _connection;
-
- internal ReconnectOperation(Connection connection)
- {
- _connection = connection;
- _connection.ReconnectCompleted += HandleReconnectCompleted;
- }
-
- private void HandleReconnectCompleted(object sender, EventArgs eventArgs)
- {
- _connection.ReconnectCompleted -= HandleReconnectCompleted;
- RaiseOperationComplete();
- }
-
- internal override void DoOperation()
- {
- if (_connection.Runspace.RunspaceStateInfo.State != RunspaceState.Disconnected)
- {
- EventHandler HandleRunspaceStateChanged = null;
- HandleRunspaceStateChanged =
- delegate(object sender, RunspaceStateEventArgs e)
- {
- if (e.RunspaceStateInfo.State == RunspaceState.Disconnected)
- {
- _connection.ReconnectAsync();
- _connection.Runspace.StateChanged -= HandleRunspaceStateChanged;
- }
- };
-
- _connection.Runspace.StateChanged += HandleRunspaceStateChanged;
-
- if (_connection.Runspace.RunspaceStateInfo.State == RunspaceState.Disconnected)
- {
- _connection.ReconnectAsync();
- _connection.Runspace.StateChanged -= HandleRunspaceStateChanged;
- }
-
- return;
- }
-
- _connection.ReconnectAsync();
- }
- }
-
- #endregion ThrottleOperation
-
- internal class ConnectionManager : RunspaceProvider, IDisposable
- {
- #region RequestInfo
-
- private class RequestInfo
- {
- private WSManConnectionInfo _connectionInfo;
- private uint _retryCount;
- private GetRunspaceAsyncResult _asyncResult;
- private uint _retryInterval;
-
- internal WSManConnectionInfo ConnectionInfo
- {
- get { return _connectionInfo; }
- set { _connectionInfo = value; }
- }
-
- internal uint RetryCount
- {
- get { return _retryCount; }
- set { _retryCount = value; }
- }
-
- internal GetRunspaceAsyncResult AsyncResult
- {
- get { return _asyncResult; }
- set { _asyncResult = value; }
- }
-
- internal uint RetryInterval
- {
- get { return _retryInterval; }
- set { _retryInterval = value; }
- }
- }
-
- #endregion RequestInfo
-
- #region Private members
-
- // this is the connection pool indexed based on a given machine
- // and a given session configuration
- private readonly ConcurrentDictionary>> _connectionPool =
- new ConcurrentDictionary>>();
-
- // this is the list of computers to which a cleanup is requested
- private readonly ConcurrentDictionary>> _cleanupComputers =
- new ConcurrentDictionary>>();
-
- private readonly int _idleTimeout;
- private readonly int _maxOutBoundConnections;
- private readonly int _maxConnectedSessions;
- private readonly int _maxDisconnectedSessions;
-
- private int _isServicing;
- private int _isServicingCallbacks;
- private int _isServicingCleanups;
- private const int Servicing = 1;
- private const int NotServicing = 0;
- private readonly Timer _timer;
- private readonly ConcurrentQueue _inComingRequests = new ConcurrentQueue();
-
- private readonly ConcurrentQueue _callbacks =
- new ConcurrentQueue();
-
- private int _timerFired;
- private const int TimerFired = 1;
- private const int TimerReset = 0;
- private bool _isDisposed;
- private bool _isDisposing;
- private readonly PowerShellTraceSource _tracer = PowerShellTraceSourceFactory.GetTraceSource();
- private readonly object _syncObject = new object();
- private static readonly PSPerfCountersMgr _perfCountersMgr = PSPerfCountersMgr.Instance;
-
-
- ///
- /// The servicing thread will release control of processing and the timer
- /// thread will take control and process based on this wait handle
- ///
- private readonly ManualResetEvent _servicingThreadRelease = new ManualResetEvent(false);
-
- ///
- /// The timer thread will release control of processing and the servicing thread
- /// will take control and process based on this wait handle
- ///
- private readonly ManualResetEvent _timerThreadRelease = new ManualResetEvent(true);
-
- ///
- /// This list is assumed to accessed by only the servicing thread and
- /// hence is not designed to be thread safe
- ///
- private readonly List _pendingRequests = new List();
-
- ///
- /// number of sessions in the connected state
- ///
- /// this is made static in the interest of time
- /// should not be static
- //internal static int ConnectedSessionCount = 0;
- private int _connectedSessionCount = 0;
-
- ///
- /// number of sessions in the disconnected state
- ///
- /// this is made static in the interest of time
- /// should not be static
- //internal static int _disconnectedSessionCount = 0;
- private int _disconnectedSessionCount = 0;
-
- private int _createdConnections = 0;
-
- ///
- /// if we need to check whether runspaces need to be
- /// disconnected
- ///
- private int _checkForDisconnect = 0;
- private const int CheckForDisconnect = 1;
- private const int DoNotCheckForDisconnect = 0;
-
- ///
- /// Map of timers for each machine
- ///
- private readonly ConcurrentDictionary _timerMap = new ConcurrentDictionary();
-
- #endregion Private Members
-
- #region Constructors
-
- internal ConnectionManager(int idleTimeout, int maxOutBoundConnections, int throttleLimit, int maxConnectedSessions, int maxDisconnectedSessions)
- {
- _idleTimeout = idleTimeout;
- _maxOutBoundConnections = maxOutBoundConnections;
- _throttleLimit = throttleLimit;
- _maxConnectedSessions = maxConnectedSessions;
- _maxDisconnectedSessions = maxDisconnectedSessions;
-
- _timer = new Timer {AutoReset = true, Interval = _idleTimeout, Enabled=false};
- _timer.Elapsed += HandleTimerElapsed;
- _timer.Start();
- }
-
- #endregion Constructors
-
- #region Interface Methods
-
- ///
- /// Get runspace for the specified connection info to be
- /// used for running commands
- ///
- /// connection info to use
- /// retry count
- /// retry interval in ms
- /// remote runspace to use
- public override Runspace GetRunspace(WSManConnectionInfo connectionInfo, uint retryCount, uint retryInterval)
- {
- IAsyncResult asyncResult = BeginGetRunspace(connectionInfo, retryCount, retryInterval, null, null);
-
- return EndGetRunspace(asyncResult);
- }
-
- ///
- /// Begin for obtaining a runspace for the specified ConnectionInfo
- ///
- /// connection info to be used for remote connections
- /// number of times to retry
- /// optional user defined callback
- /// optional user specified state
- /// time in milliseconds before the next retry has to be attempted
- /// async result
- public override IAsyncResult BeginGetRunspace(WSManConnectionInfo connectionInfo, uint retryCount, uint retryInterval, AsyncCallback callback, object state)
- {
- GetRunspaceAsyncResult result = new GetRunspaceAsyncResult(state, callback, Guid.Empty);
-
- // Create a Request Object and queue the same
- RequestInfo requestInfo = new RequestInfo
- {
- ConnectionInfo = connectionInfo,
- RetryCount = retryCount,
- AsyncResult = result,
- RetryInterval = retryInterval
- };
-
- _tracer.WriteMessage("PSW ConnMgr: New incoming request for runspace queued");
- _inComingRequests.Enqueue(requestInfo);
- _perfCountersMgr.UpdateCounterByValue(
- PSWorkflowPerformanceCounterSetInfo.CounterSetId,
- PSWorkflowPerformanceCounterIds.PSRemotingPendingRequestsQueueLength);
-
- // start servicing thread if required
- CheckAndStartRequiredThreads();
-
- return result;
- }
-
- ///
- /// End for obtaining a runspace for the specified connection info
- ///
- /// async result to end on
- /// remote runspace to invoke commands on
- public override Runspace EndGetRunspace(IAsyncResult asyncResult)
- {
- if (asyncResult == null)
- throw new ArgumentNullException("asyncResult");
-
- GetRunspaceAsyncResult result = asyncResult as GetRunspaceAsyncResult;
-
- if (result == null)
- throw new ArgumentException(Resources.InvalidAsyncResultSpecified, "asyncResult");
-
- AssertNotDisposed();
-
- // this will throw an exception when a runspace is not successfully
- // available
- result.EndInvoke();
-
- Debug.Assert(result.Connection != null, "EndInvoke() should throw an exception if connection is null");
-
- _tracer.WriteMessage("PSW ConnMgr: Request serviced and runspace returned");
- Runspace runspace = result.Connection != null ? result.Connection.Runspace : null;
-
- return runspace;
- }
-
- ///
- /// Release the runspace once the activity is done using the same
- ///
- /// runspace to release
- public override void ReleaseRunspace(Runspace runspace)
- {
- AssertNotDisposed();
-
- Connection connection = GetConnectionForRunspace(runspace);
- _tracer.WriteMessage("PSW ConnMgr: Runspace released");
-
- // at this point connection will be not null
- // since GetConnectionForRunspace() should have
- // handled all cases and raised an exception
- Debug.Assert(connection != null, "GetConnectionForRunspace has not handled all cases and raised an exception");
-
- connection.Busy = false;
- connection.AsyncResult = null;
-
- CheckAndStartRequiredThreads();
- }
-
- ///
- /// Request a cleanup to the destination specified in the
- /// connection info. This means no runspaces will be held
- /// to the specified connection info.
- ///
- /// connection info to which
- /// cleanup is desired
- ///callback to invoke
- /// caller specified state
- public override void RequestCleanup(WSManConnectionInfo connectionInfo, WaitCallback callback, object state)
- {
- if (_isDisposed || _isDisposing)
- {
- if (callback != null)
- {
- callback(state);
- }
-
- return;
- }
-
- // add this computer to the list of cleanup computers
- string computerName = connectionInfo.ComputerName;
-
- ConcurrentQueue> callbacks =
- _cleanupComputers.GetOrAdd(computerName, new ConcurrentQueue>());
-
- var tuple = new Tuple(callback, state);
- callbacks.Enqueue(tuple);
-
- CheckAndStartCleanupThread();
- }
-
- ///
- /// Checks to see if the provider intentionally disconnected a runspace
- /// or it went into disconnected state due to network issues
- ///
- /// runspace that needs to be checked
- /// true - when intentionally disconnected
- /// false - disconnected due to network issues
- public override bool IsDisconnectedByRunspaceProvider(Runspace runspace)
- {
- Connection connection = GetConnectionForRunspace(runspace);
- return connection.DisconnectedIntentionally;
- }
-
- internal void DisconnectCalled()
- {
- lock (_syncObject)
- {
- _disconnectedSessionCount++;
- _connectedSessionCount--;
- }
- }
- internal void ReconnectCalled()
- {
- lock (_syncObject)
- {
- _connectedSessionCount++;
- _disconnectedSessionCount--;
- }
- }
-
- #endregion Interface Methods
-
- #region Private Methods
-
- private static void ThrowInvalidRunspaceException(Runspace runspace)
- {
- throw new ArgumentException(Resources.InvalidRunspaceSpecified, "runspace");
- }
-
- ///
- /// Handle the idle timer event
- ///
- /// unused
- /// unused
- private void HandleTimerElapsed(object sender, ElapsedEventArgs e)
- {
- // ensure that the servicing thread is done before proceeding
- if (Interlocked.CompareExchange(ref _timerFired, TimerFired, TimerReset) == TimerFired)
- {
- _tracer.WriteMessage("PSW ConnMgr: Another timer thread is already servicing return");
- return;
- }
-
- if (_isDisposed || _isDisposing)
- {
- return;
- }
-
- try
- {
- _tracer.WriteMessage("PSW ConnMgr: Timer fired");
-
- _servicingThreadRelease.WaitOne();
- _timerThreadRelease.Reset();
-
- _tracer.WriteMessage("PSW ConnMgr: Timer servicing started");
-
- // when the timer elapses mark all unused connections to be closed
- Collection toRemoveComputer = new Collection();
-
- foreach (string computername in _connectionPool.Keys)
- {
- ConcurrentDictionary> table = _connectionPool[computername];
-
- Collection toRemoveConfig = new Collection();
- foreach (string configName in table.Keys)
- {
- ConcurrentDictionary connections = table[configName];
- Collection toRemoveConnections = new Collection();
-
- lock (_syncObject)
- {
- foreach (Connection connection in connections.Values)
- {
- // if connection has been marked idle the last
- // time remove resources
- if (connection.Idle)
- {
- toRemoveConnections.Add(connection);
- }
- else if (!connection.Busy)
- {
- connection.Idle = true;
- }
- }
- }
-
- // remove all connections that need to be removed
- foreach (Connection connection in toRemoveConnections)
- {
- Connection removeConnection;
- _createdConnections--;
- // remove connection from the table before attempting to
- // close it. This will ensure that this connection is not
- // assigned by mistake
- connections.TryRemove(connection.InstanceId, out removeConnection);
- _tracer.WriteMessage(String.Format(CultureInfo.InvariantCulture, "Closing idle connection to {0}", connection.Runspace.ConnectionInfo.ComputerName));
- SubmitOperation(new CloseOperation(connection));
- }
-
- // if there are no more entries in connections it needs
- // to be removed from the table
- if (connections.Count == 0)
- {
- toRemoveConfig.Add(configName);
- }
-
- } // go through all configurations for a specified computer
-
- foreach (string configName in toRemoveConfig)
- {
- ConcurrentDictionary removedConnections;
- table.TryRemove(configName, out removedConnections);
- }
-
- // if there are no more entries in table it needs to be removed
- // from the connection pool
- if (table.Keys.Count == 0)
- {
- toRemoveComputer.Add(computername);
- }
-
- } // go through all computernames
-
- // remove unwanted computernames from the connectionpool
- foreach (string computerName in toRemoveComputer)
- {
- ConcurrentDictionary> removedTable;
- _connectionPool.TryRemove(computerName, out removedTable);
- }
-
- _tracer.WriteMessage("PSW ConnMgr: Timer servicing completed");
-
- Interlocked.CompareExchange(ref _timerFired, TimerReset, TimerFired);
- _timerThreadRelease.Set();
- }
- catch (ObjectDisposedException)
- {
- // Ignoring this exception
- }
- finally
- {
- CheckAndStartRequiredThreads();
- }
- }
-
- private void TraceThreadPoolInfo(string message)
- {
-#if DEBUG
- int maxWorkerThreads, maxCompletionPortThreads, availableWorkerThreads, availableCompletionPortThreads,
- minWorkerThreads, minCompletionPortThreads;
-
- ThreadPool.GetMinThreads(out minWorkerThreads, out minCompletionPortThreads);
- ThreadPool.GetMaxThreads(out maxWorkerThreads, out maxCompletionPortThreads);
- ThreadPool.GetAvailableThreads(out availableWorkerThreads, out availableCompletionPortThreads);
-
- _tracer.WriteMessage(string.Format(System.Globalization.CultureInfo.InvariantCulture,
- "PSW ConnMgr: {0} minwt:{1} mincpt:{2} wt:{3} ct:{4} awt:{5} act:{6}",
- message, minWorkerThreads, minCompletionPortThreads, maxWorkerThreads,
- maxCompletionPortThreads, availableWorkerThreads,
- availableCompletionPortThreads));
-#else
- _tracer.WriteMessage(string.Format(System.Globalization.CultureInfo.InvariantCulture,
- "PSW ConnMgr: {0}",
- message));
-#endif
- }
-
- ///
- /// Checks to see if a thread is already servicing and if not starts one
- ///
- private void CheckAndStartConnectionServicingThread()
- {
- if (Interlocked.CompareExchange(ref _isServicing, Servicing, NotServicing) != NotServicing) return;
-
- TraceThreadPoolInfo("QueueUserWorkItem Connection Servicing thread");
- ThreadPool.QueueUserWorkItem(ServiceRequests);
- }
-
- ///
- /// Checks to see if a thread is already servicing callbacks
- /// and if not starts one
- ///
- private void CheckAndStartCallbackServicingThread()
- {
- if (Interlocked.CompareExchange(ref _isServicingCallbacks, Servicing, NotServicing) != NotServicing) return;
-
- TraceThreadPoolInfo("Callback thread");
- ThreadPool.QueueUserWorkItem(ServiceCallbacks);
- }
-
- ///
- /// Method that services the callbacks for all
- /// successfully assigned runspaces
- ///
- /// unused
- private void ServiceCallbacks(object state)
- {
- if (_isDisposed || _isDisposing)
- {
- return;
- }
-
- GetRunspaceAsyncResult result;
- while (_callbacks.TryDequeue(out result))
- {
- result.SetAsCompleted(null);
- }
-
- // release servicing callbacks
- Interlocked.CompareExchange(ref _isServicingCallbacks, NotServicing, Servicing);
- }
-
- internal void AddToPendingCallback(GetRunspaceAsyncResult asyncResult)
- {
- _callbacks.Enqueue(asyncResult);
- CheckAndStartCallbackServicingThread();
- }
-
- private void CheckAndStartRequiredThreads()
- {
- if (_isDisposed || _isDisposing)
- {
- return;
- }
-
- CheckAndStartConnectionServicingThread();
- CheckAndStartDisconnectReconnectThread();
- CheckAndStartThrottleManagerThread();
- CheckAndStartCleanupThread();
- }
-
- ///
- /// Method that contains the core servicing logic
- ///
- /// not used
- private void ServiceRequests(object state)
- {
- try
- {
- TraceThreadPoolInfo("Starting servicing thread");
-
- // ensure that idle timer thread has completed execution
- // before proceeding
- _timerThreadRelease.WaitOne();
- _servicingThreadRelease.Reset();
-
- if (NeedToReturnFromServicing())
- {
- return;
- }
-
- Collection toRemove = new Collection();
-
- // service all pending requests
- foreach (RequestInfo info in _pendingRequests)
- {
- if (ServiceOneRequest(info)) toRemove.Add(info);
-
- if (NeedToReturnFromServicing())
- {
- return;
- }
- }
-
- // remove serviced requests from pending queues
- foreach (RequestInfo info in toRemove)
- {
- _pendingRequests.Remove(info);
- _perfCountersMgr.UpdateCounterByValue(
- PSWorkflowPerformanceCounterSetInfo.CounterSetId,
- PSWorkflowPerformanceCounterIds.PSRemotingForcedToWaitRequestsQueueLength,
- -1);
-
- }
-
- // if timer has fired, return
- if (NeedToReturnFromServicing())
- {
- return;
- }
-
- // start servicing the incoming requests
- RequestInfo requestInfo;
- while (_inComingRequests.TryDequeue(out requestInfo))
- {
- _perfCountersMgr.UpdateCounterByValue(
- PSWorkflowPerformanceCounterSetInfo.CounterSetId,
- PSWorkflowPerformanceCounterIds.PSRemotingPendingRequestsQueueLength,
- -1);
- if (!ServiceOneRequest(requestInfo))
- {
- // the request could not be serviced now
- // add it to the pending queue
- _pendingRequests.Add(requestInfo);
- _perfCountersMgr.UpdateCounterByValue(
- PSWorkflowPerformanceCounterSetInfo.CounterSetId,
- PSWorkflowPerformanceCounterIds.PSRemotingForcedToWaitRequestsQueueLength);
- }
-
- if (NeedToReturnFromServicing())
- {
- return;
- }
-
- } // service incoming requests
- }
- catch (ObjectDisposedException)
- {
- //
- }
- finally
- {
- // set servicing as complete
- SafelyReturnFromServicing();
-
- // Try to start the servicing thread again if there are any _inComingRequests.
- // This is required to fix the race condition between CheckAndStartRequiredThreads() and ServiceRequests() methods.
- //
- if (_inComingRequests.Count > 0)
- {
- CheckAndStartConnectionServicingThread();
- }
- }
- }
-
- ///
- /// Services one single request
- ///
- /// request to service
- /// true, if successfully serviced, false otherwise
- private bool ServiceOneRequest(RequestInfo requestInfo)
- {
- string computerName = requestInfo.ConnectionInfo.ComputerName;
- string configName = requestInfo.ConnectionInfo.ShellUri;
-
- // if a cleanup is requested for a specified computer
- // do not service the request until it is good to do so
- if (_cleanupComputers.ContainsKey(computerName))
- return false;
-
- int existingConnections = 0;
- _perfCountersMgr.UpdateCounterByValue(
- PSWorkflowPerformanceCounterSetInfo.CounterSetId,
- PSWorkflowPerformanceCounterIds.PSRemotingRequestsBeingServicedCount);
-
- // check if there is a table for this computername
- ConcurrentDictionary> table =
- _connectionPool.GetOrAdd(computerName,
- new ConcurrentDictionary>());
-
- // count the number of existing connections to this computer
- existingConnections = table.Keys.Sum(key => table[key].Count);
-
- // check if there is a connection collection for the specified configuration
- ConcurrentDictionary connections = table.GetOrAdd(configName,
- new ConcurrentDictionary
- ());
-
- bool activityResumption = false;
- RunCommandsArguments args = requestInfo.AsyncResult.AsyncState as RunCommandsArguments;
-
- if (args != null && args.ImplementationContext != null)
- activityResumption = !args.ImplementationContext.DisconnectedRunspaceInstanceId.Equals(Guid.Empty);
-
- // Existing connections should not be used when remote activity is resuming as they have a valid remote runspace
- // Remote activity resume operation has to reconnect to the disconnected runspace
- if (!activityResumption)
- {
- // table is available, check if there are any free runspaces
- // if the collections was newly created, then this loop will
- // be skipped)
- foreach (Connection connection in
- connections.Values.Where(connection => !connection.Busy).Where(connection => ValidateConnection(requestInfo, connection)))
- {
- // the assumption is connected session count and
- // disconnected session count apply only to running
- // pipelines. So a connection that is not busy will
- // not be in the disconnected state
- //Debug.Assert(connection.Runspace.RunspaceStateInfo.State != RunspaceState.Disconnected,
- // "A not Busy connection should not be in the disconnected state");
- _tracer.WriteMessage("PSW ConnMgr: Assigning existing connection to request");
- AssignConnection(requestInfo, connection);
- _perfCountersMgr.UpdateCounterByValue(
- PSWorkflowPerformanceCounterSetInfo.CounterSetId,
- PSWorkflowPerformanceCounterIds.PSRemotingRequestsBeingServicedCount,
- -1);
- return true;
- }
- }
-
- if (existingConnections < _maxOutBoundConnections)
- {
- _tracer.WriteMessage("PSW ConnMgr: Creating new connection to service request");
- // the number of connections hasn't maxed out for this
- // computer - a new connection can be created
- Connection connection = CreateConnection(requestInfo, connections);
-
- // when the open succeeds within the specified retry attempts
- // the connection will be assigned.
- // submit the connection to the pending operations queue instead
- // of opening it directly
- SubmitOperation(new OpenOperation(connection));
- _perfCountersMgr.UpdateCounterByValue(
- PSWorkflowPerformanceCounterSetInfo.CounterSetId,
- PSWorkflowPerformanceCounterIds.PSRemotingRequestsBeingServicedCount,
- -1);
- return true;
- }
-
- // when the existing connections are maxed out, there
- // are one of two choices
- // 1. all connections are busy, in which case
- // the request cannot be serviced
- // 2. there are some idle connections, which
- // can be closed and a new one created
-
- Connection potentialConnection = null;
-
- // find the first available idle connection
- ConcurrentDictionary removeConnections=null;
-
- foreach (var key in table.Keys)
- {
- removeConnections = table[key];
-
- potentialConnection = removeConnections.Values.Where(connection => !connection.Busy).FirstOrDefault();
-
- if (potentialConnection != null) break;
- }
-
- if (potentialConnection == null)
- {
- _perfCountersMgr.UpdateCounterByValue(
- PSWorkflowPerformanceCounterSetInfo.CounterSetId,
- PSWorkflowPerformanceCounterIds.PSRemotingRequestsBeingServicedCount,
- -1);
- return false; /* case 1 */
- }
-
- // it is possible that the potential connection in fact
- // is a good match, if so return the same
- // Existing connections should not be used when remote activity is resuming as they have a valid remote runspace
- // Remote activity resume operation has to reconnect to the disconnected runspace
- if (!activityResumption && ValidateConnection(requestInfo, potentialConnection))
- {
- _tracer.WriteMessage("PSW ConnMgr: Assigning potential connection to service request");
- AssignConnection(requestInfo, potentialConnection);
- _perfCountersMgr.UpdateCounterByValue(
- PSWorkflowPerformanceCounterSetInfo.CounterSetId,
- PSWorkflowPerformanceCounterIds.PSRemotingRequestsBeingServicedCount,
- -1);
- return true;
- }
-
- // there is a potential connection which can be closed,
- // close the same and create a new one
- removeConnections.TryRemove(potentialConnection.InstanceId, out potentialConnection);
-
- Debug.Assert(potentialConnection != null, "Trying to remove an element not in the dictionary");
- _tracer.WriteMessage("PSW ConnMgr: Closing potential connection and creating a new one to service request");
-
- // Create the connection object which will be returned after
- // the potential connection is closed
- _createdConnections--;
- Connection newConnection = CreateConnection(requestInfo, connections);
- _perfCountersMgr.UpdateCounterByValue(
- PSWorkflowPerformanceCounterSetInfo.CounterSetId,
- PSWorkflowPerformanceCounterIds.PSRemotingConnectionsClosedReopenedCount);
- SubmitOperation(new CloseOneAndOpenAnotherOperation(potentialConnection, newConnection));
- _perfCountersMgr.UpdateCounterByValue(
- PSWorkflowPerformanceCounterSetInfo.CounterSetId,
- PSWorkflowPerformanceCounterIds.PSRemotingRequestsBeingServicedCount,
- -1);
- return true;
- }
-
- private Connection CreateConnection(RequestInfo requestInfo, ConcurrentDictionary connections)
- {
- Connection connection = new Connection(this)
- {
- ConnectionInfo = requestInfo.ConnectionInfo,
- RetryCount = requestInfo.RetryCount,
- RetryInterval = requestInfo.RetryInterval,
- RetryAttempt = 0,
- AsyncResult = requestInfo.AsyncResult,
- Busy = true
- };
-
- // the busy status should be set before adding to the
- // collection so that this connection is accounted in
- // the total and is not assigned to another request
- connections.TryAdd(connection.InstanceId, connection);
-
- _createdConnections++;
- _perfCountersMgr.UpdateCounterByValue(
- PSWorkflowPerformanceCounterSetInfo.CounterSetId,
- PSWorkflowPerformanceCounterIds.PSRemotingConnectionsCreatedCount);
- return connection;
- }
-
- ///
- /// Do everything required so that servicing thread can return
- ///
- private void SafelyReturnFromServicing()
- {
- if (_isDisposed || _isDisposing)
- {
- return;
- }
-
- CheckAndStartRequiredThreads();
-
- try
- {
- _tracer.WriteMessage("PSW ConnMgr: Safely returning from servicing");
- Interlocked.CompareExchange(ref _isServicing, NotServicing, Servicing);
- _servicingThreadRelease.Set();
- }
- catch (ObjectDisposedException)
- {
- // Ignoring ObjectDisposedException
- }
- }
-
- ///
- /// Check if the servicing thread need to stop processing requests
- ///
- /// true if processing needs to stop
- private bool NeedToReturnFromServicing()
- {
- if(_isDisposed || _isDisposing)
- {
- _tracer.WriteMessage("PSW ConnMgr: Returning from servicing as ConnMgr is disposed or being disposed");
- return true;
- }
-
- // servicing thread has to return if the timer
- // has been fired
- if (_timerFired == TimerFired)
- {
- _tracer.WriteMessage("PSW ConnMgr: Returning from servicing since timer fired");
- return true;
- }
-
- if (_createdConnections >= _maxConnectedSessions)
- {
- _tracer.WriteMessage("PSW ConnMgr: Setting check for runspaces disconnect flag");
- Interlocked.CompareExchange(ref _checkForDisconnect, CheckForDisconnect, DoNotCheckForDisconnect);
- }
-
- return false;
- }
-
- private static bool ValidateConnection(RequestInfo requestInfo, Connection connection)
- {
- if (connection.Runspace.RunspaceStateInfo.State != RunspaceState.Opened ) return false;
-
- WSManConnectionInfo connectionInfo = requestInfo.ConnectionInfo;
-
- // when validation is called the Connection will have a runspace populated
- WSManConnectionInfo connectionInfo2 = connection.Runspace.OriginalConnectionInfo as WSManConnectionInfo;
-
- // Runspace.OriginalConnectionInfo is null for disconnected runspace after process crash
- if(connectionInfo2 == null)
- connectionInfo2 = connection.Runspace.ConnectionInfo as WSManConnectionInfo;
-
- if (connectionInfo2 == null) return false;
-
- // check URI related stuff
- if (!WorkflowUtils.CompareConnectionUri(connectionInfo, connectionInfo2))
- {
- return false;
- }
-
- // compare shell URI
- if (!WorkflowUtils.CompareShellUri(connectionInfo.ShellUri, connectionInfo2.ShellUri))
- {
- return false;
- }
-
- // check authentication
- if (!WorkflowUtils.CompareAuthentication(connectionInfo.AuthenticationMechanism, connectionInfo2.AuthenticationMechanism))
- {
- return false;
- }
-
- // check credentials if present
- if(!WorkflowUtils.CompareCredential(connectionInfo.Credential, connectionInfo2.Credential))
- {
- return false;
- }
-
- //check certificate thumbprint
- if (!WorkflowUtils.CompareCertificateThumbprint(connectionInfo.CertificateThumbprint, connectionInfo2.CertificateThumbprint))
- {
- return false;
- }
-
- //check proxy settings
- if (!WorkflowUtils.CompareProxySettings(connectionInfo, connectionInfo2))
- {
- return false;
- }
-
- //check rest of wsman settings
- if (!WorkflowUtils.CompareOtherWSManSettings(connectionInfo, connectionInfo2))
- {
- return false;
- }
-
- // check open timeout
- if (connectionInfo2.IdleTimeout < connectionInfo.IdleTimeout)
- return false;
-
- return true;
- }
-
- ///
- /// Service the request using the available connection
- ///
- /// request to service
- /// connection to use for servicing
- private void AssignConnection(RequestInfo requestInfo, Connection connection)
- {
- IAsyncResult asyncResult = requestInfo.AsyncResult;
- GetRunspaceAsyncResult result = asyncResult as GetRunspaceAsyncResult;
- Debug.Assert(result != null, "IAsyncResult should be GetRunspaceAsyncResult");
-
- connection.Busy = true;
-
- connection.AsyncResult = result;
- result.Connection = connection;
-
- AddToPendingCallback(result);
- }
-
- ///
- /// Find the connection object given a runspace
- ///
- /// runspace whose connection
- /// needs to be found
- /// Connection if found, null otherwise
- private Connection GetConnectionForRunspace(Runspace runspace)
- {
- if (runspace == null)
- throw new ArgumentNullException("runspace");
-
- // OriginalConnectionInfo will be null for reconnected remoterunspace after crash or shutdown
- WSManConnectionInfo connectionInfo = runspace.ConnectionInfo as WSManConnectionInfo;
-
- if (connectionInfo == null)
- {
- _tracer.WriteMessage("PSW ConnMgr: Incoming connectioninfo is null");
- // throw an exception here
- ThrowInvalidRunspaceException(runspace);
- }
-
- string computername = connectionInfo.ComputerName;
- string configname = connectionInfo.ShellUri;
-
- ConcurrentDictionary> table;
- ConcurrentDictionary connections;
-
- if (!_connectionPool.TryGetValue(computername, out table))
- {
- // invalid runspace specified, throw an exception here
- _tracer.WriteMessage("PSW ConnMgr: Cannot find table for computername " + computername);
- ThrowInvalidRunspaceException(runspace);
- }
-
- if (!table.TryGetValue(configname, out connections))
- {
- // invalid runspace specified, throw an exception here
- _tracer.WriteMessage("PSW ConnMgr: Cannot find list for config " + configname);
- ThrowInvalidRunspaceException(runspace);
- }
-
- foreach (Connection connection in
- connections.Values.Where(connection => connection.Runspace != null).Where(connection => connection.Runspace.InstanceId == runspace.InstanceId))
- {
- return connection;
- }
-
- // if this point is reached, then there is no match
- // invalid runspace specified, throw an exception
- _tracer.WriteMessage("PSW ConnMgr: Cannot find the actual connection object");
- ThrowInvalidRunspaceException(runspace);
-
- return null;
- }
-
- ///
- /// Check and start a method which will do cleanups to
- /// the specified computer
- ///
- private void CheckAndStartCleanupThread()
- {
- if (Interlocked.CompareExchange(ref _isServicingCleanups, Servicing, NotServicing) != NotServicing)
- return;
-
- TraceThreadPoolInfo("Cleanup thread");
-
- ThreadPool.QueueUserWorkItem(ServiceCleanupRequests);
- }
-
- ///
- /// Worker method for servicing cleanups to requested computers
- ///
- ///
- private void ServiceCleanupRequests(object state)
- {
-
- foreach (string computerName in _cleanupComputers.Keys)
- {
- ConcurrentDictionary> table;
- _connectionPool.TryGetValue(computerName, out table);
-
- if (table == null)
- {
- RaiseCallbacksAfterCleanup(computerName);
- continue;
- }
-
- foreach (string configName in table.Keys)
- {
- ConcurrentDictionary connections;
- table.TryGetValue(configName, out connections);
-
- if (connections == null) continue;
- lock (_syncObject)
- {
- foreach (CloseOperation closeOperation in
- connections.Values.Where(connection => !connection.Busy).Select(connection => new CloseOperation(connection)))
- {
- closeOperation.OperationComplete += HandleCloseOperationComplete;
- SubmitOperation(closeOperation);
- }
- }
- }
- }
-
- Interlocked.CompareExchange(ref _isServicingCleanups, NotServicing, Servicing);
- }
-
- ///
- /// Handles OperationComplete of close operations i.e
- /// when connections to a specified computer is closed
- ///
- /// the CloseOperation object
- /// that initiated this event
- /// event parameters
- private void HandleCloseOperationComplete(object sender, EventArgs e)
- {
- // the specified connection was successfully closed
- CloseOperation closeOperation = sender as CloseOperation;
- Debug.Assert(closeOperation != null, "CloseOperation object need to be returned in OperationComplete event");
- closeOperation.OperationComplete -= HandleCloseOperationComplete;
-
- Connection connection = closeOperation.Connection;
- WSManConnectionInfo connectionInfo = connection.Runspace.ConnectionInfo as WSManConnectionInfo;
- if (connectionInfo == null) return;
-
- string computerName = connectionInfo.ComputerName;
- string configName = connectionInfo.ShellUri;
-
- ConcurrentDictionary> table;
- _connectionPool.TryGetValue(computerName, out table);
- if (table == null) return;
-
- ConcurrentDictionary connections;
- table.TryGetValue(configName, out connections);
- if (connections == null) return;
-
- // remove the connection from the table for this configName
- Connection removedConnection;
- connections.TryRemove(connection.InstanceId, out removedConnection);
- if (connections.Count != 0) return;
-
- // if there are no more connections to this configName
- // remove the table for the configName
- ConcurrentDictionary removedConnections;
- table.TryRemove(configName, out removedConnections);
- if (table.Count != 0) return;
-
- // if there are no more tables for any specified configNames
- // for this computerName, remove the table for the computerName
- ConcurrentDictionary> removedTable;
- _connectionPool.TryRemove(computerName, out removedTable);
-
- if (removedTable != null)
- {
- // if this thread is the one that removed the table, then
- // make all the callbacks in this thread
- RaiseCallbacksAfterCleanup(computerName);
- }
- }
-
- ///
- /// Raise all the callbacks to the specified computer
- /// after the requested cleanup
- ///
- /// computer to which the
- /// callback needs to be raised
- private void RaiseCallbacksAfterCleanup(string computerName)
- {
- bool alreadyAdded = _timerMap.Values.Contains(computerName, StringComparer.OrdinalIgnoreCase);
-
- // before making the callbacks fire the timer
- Timer timer = new Timer();
- _timerMap.TryAdd(timer, computerName);
-
- timer.Elapsed += HandleCleanupWaitTimerElapsed;
-
- ConcurrentQueue> waitCallbacks;
- if (!_cleanupComputers.TryGetValue(computerName, out waitCallbacks))
- {
- _tracer.WriteMessage("PSW ConnMgr: Cannot find specified computer in _waitCallbacks dictionary: " + computerName);
- return;
- }
-
- Tuple tuple;
- Collection> callbacks = new Collection>();
-
- int highest = 0;
- bool calledFromActivity = false;
-
- while (waitCallbacks.TryDequeue(out tuple))
- {
- if (tuple.Item2 != null)
- {
- RunCommandsArguments args = tuple.Item2 as RunCommandsArguments;
-
- if (args != null)
- {
- if (highest < args.CleanupTimeout)
- {
- highest = args.CleanupTimeout;
- }
-
- calledFromActivity = true;
- }
- }
-
- callbacks.Add(tuple);
- }
-
- if (highest != 0)
- {
- timer.Interval = highest * 1000;
- timer.AutoReset = false;
- timer.Enabled = true;
-
- foreach (Tuple t in callbacks)
- {
- if (t.Item1 != null)
- t.Item1(t.Item2);
- }
- }
- else
- {
- if (!alreadyAdded)
- {
- HandleCleanupWaitTimerElapsed(timer, null);
- }
- else
- {
- string unused;
- _timerMap.TryRemove(timer, out unused);
- }
- }
-
- if (!calledFromActivity)
- {
- foreach(var callbackTuple in callbacks)
- {
- if (callbackTuple.Item1 != null)
- callbackTuple.Item1(callbackTuple.Item2);
- }
- }
- }
-
- ///
- /// Timer elapsed handler for the specified computer. Once
- /// the timer elapses, new connections to the specified
- /// computer will be allowed
- ///
- /// timer that generated the event
- /// event arguments
- private void HandleCleanupWaitTimerElapsed(object sender, ElapsedEventArgs e)
- {
- Timer timer = sender as Timer;
- Debug.Assert(timer != null, "Sender cannot be null");
-
- string computerName;
- _timerMap.TryGetValue(timer, out computerName);
- if (!string.IsNullOrEmpty(computerName))
- {
- ConcurrentQueue> removedCallbacks;
- _cleanupComputers.TryRemove(computerName, out removedCallbacks);
- }
-
- // remove entry from the timer map and do cleanup
- _timerMap.TryRemove(timer, out computerName);
-
- timer.Elapsed -= HandleCleanupWaitTimerElapsed;
- timer.Dispose();
-
- CheckAndStartRequiredThreads();
- }
-
- #endregion Private Methods
-
- #region Test Helper Methods
-
- internal bool IsConnectionPoolEmpty()
- {
- return _connectionPool.Keys.Count > 0;
- }
-
- internal IEnumerable GetConnectionEnumerator()
- {
- return new ConnectionEnumerator(_connectionPool);
- }
- #endregion Test Helper Methods
-
- #region Dispose
-
- ///
- /// Dispose the connection manager
- ///
- public void Dispose()
- {
- Dispose(true);
- GC.SuppressFinalize(this);
- }
-
- ///
- /// Dispose the connection manager
- ///
- ///
- protected void Dispose(bool isDisposing)
- {
- if (_isDisposed || !isDisposing)
- return;
-
- lock (_syncObject)
- {
- if (_isDisposed)
- return;
-
- _isDisposing = true;
-
- // set these values to servicing so that a thread is
- // not started
- Interlocked.CompareExchange(ref _isServicing, Servicing, NotServicing);
- Interlocked.CompareExchange(ref _isServicingCallbacks, Servicing, NotServicing);
- Interlocked.CompareExchange(ref _isServicingCleanups, Servicing, NotServicing);
- Interlocked.CompareExchange(ref _timerFired, TimerFired, TimerReset);
-
- // close and clear all connections in connection pool
- ClearAll();
-
- // This should be done after closing all connections.
- // Throttling thread executes the close operations
- Interlocked.CompareExchange(ref _isOperationsServiced, Servicing, NotServicing);
-
- _timer.Elapsed -= HandleTimerElapsed;
- _timer.Dispose();
-
- var objectDisposedException = new ObjectDisposedException("ConnectionManager");
- GetRunspaceAsyncResult item;
- while (_callbacks.TryDequeue(out item))
- {
- item.SetAsCompleted(objectDisposedException);
- }
- _cleanupComputers.Clear();
-
- RequestInfo info;
- while (_inComingRequests.Count > 0)
- {
- _inComingRequests.TryDequeue(out info);
- info.AsyncResult.SetAsCompleted(objectDisposedException);
- }
-
- foreach(var reqInfo in _pendingRequests)
- {
- reqInfo.AsyncResult.SetAsCompleted(objectDisposedException);
- }
- _pendingRequests.Clear();
-
- ThrottleOperation operation;
- while (_pendingQueue.Count > 0)
- {
- _pendingQueue.TryDequeue(out operation);
- }
-
- _timerMap.Clear();
- _servicingThreadRelease.Close();
- _timerThreadRelease.Close();
- _testHelperCloseDone.Close();
- _tracer.Dispose();
-
- _isDisposed = true;
- }
- }
-
- private void AssertNotDisposed()
- {
- if (_isDisposed)
- {
- throw new ObjectDisposedException("ConnectionManager");
- }
- }
- #endregion Dispose
-
- #region Throttling
-
- ///
- /// queue of operations to be used for throttling
- ///
- private readonly ConcurrentQueue _pendingQueue = new ConcurrentQueue();
-
- ///
- /// Count of operations in progress
- ///
- private int _inProgressCount = 0;
-
- ///
- /// throttle limit - includes open/close/connect/disconnect operations
- ///
- private readonly int _throttleLimit;
-
- ///
- /// is the queue of operations being serviced
- ///
- private int _isOperationsServiced;
-
- ///
- /// submit an operation to the queue
- ///
- /// operation to submit
- private void SubmitOperation(ThrottleOperation operation)
- {
- _pendingQueue.Enqueue(operation);
- CheckAndStartThrottleManagerThread();
- }
-
- private void CheckAndStartThrottleManagerThread()
- {
- // if not already set, set flag that pending operations queue is being serviced
- // else another thread is already servicing so return
- if (Interlocked.CompareExchange(ref _isOperationsServiced, Servicing, NotServicing) != NotServicing) return;
-
- TraceThreadPoolInfo("Queuing user workitem Running operations in throttle queue");
-
- ThreadPool.QueueUserWorkItem(StartOperationsFromQueue);
- }
-
- ///
- /// Start operations upto throttle limit from the queue
- ///
- /// this method is thread safe. It starts all pending
- /// operations in the first calling thread. The assumption here
- /// is that starting a few operations isn't expensive and so
- /// the calling thread is not blocked for a long period of time
- private void StartOperationsFromQueue(object state)
- {
- if (_isDisposed)
- {
- return;
- }
-
- TraceThreadPoolInfo("Running operations in throttle queue");
-
- // at this point, there will be only one thread which will be
- // servicing operations from the pending operations queue
- ThrottleOperation operation;
-
- while (_inProgressCount < _throttleLimit && _pendingQueue.TryDequeue(out operation))
- {
- operation.OperationComplete += HandleOperationComplete;
- Interlocked.Increment(ref _inProgressCount);
- operation.DoOperation();
- }
-
- _tracer.WriteMessage("PSW ConnMgr: Done throttling");
- // set flag that pending operations queue is not being serviced
- Interlocked.CompareExchange(ref _isOperationsServiced, NotServicing, Servicing);
- }
-
- private void HandleOperationComplete (Object sender, EventArgs e)
- {
- ThrottleOperation operation = sender as ThrottleOperation;
- Debug.Assert(operation != null, "OperationComplete event does not pass ThrottleOperation as sender");
- operation.OperationComplete -= HandleOperationComplete;
- Interlocked.Decrement(ref _inProgressCount);
- CheckAndStartRequiredThreads();
- }
-
- #endregion Throttling
-
- #region Connection Enumerator
-
- private class ConnectionEnumerator : IEnumerator, IEnumerable
- {
- private Connection _currentConnection;
- private ConcurrentDictionary _currentConnections;
- private ConcurrentDictionary> _currentTable;
- private readonly IEnumerator _tableEnumerator;
- private IEnumerator _configEnumerator;
- private IEnumerator _connectionEnumerator;
-
- private readonly ConcurrentDictionary>>
- _connectionPool;
-
- internal ConnectionEnumerator(ConcurrentDictionary>> connectionPool)
- {
- Debug.Assert(connectionPool != null, "ConnectionPool cannot be null");
- _connectionPool = connectionPool;
- _tableEnumerator = _connectionPool.Keys.GetEnumerator();
- }
-
- ///
- ///
- ///
- ///
- public bool MoveNext()
- {
- while (true)
- {
- if (_connectionEnumerator != null && _connectionEnumerator.MoveNext())
- {
- Guid key = (Guid) _connectionEnumerator.Current;
- _currentConnection = null;
- _currentConnections.TryGetValue(key, out _currentConnection);
- if (_currentConnection != null)
- return true;
- else
- continue;
- }
-
- if (_configEnumerator != null && _configEnumerator.MoveNext())
- {
- string configName = (string)_configEnumerator.Current;
- _currentTable.TryGetValue(configName, out _currentConnections);
- _connectionEnumerator = _currentConnections.Keys.GetEnumerator();
-
- Debug.Assert(_connectionEnumerator != null, "Enumerator should not be null");
-
- continue;
- }
-
- if (_tableEnumerator.MoveNext())
- {
- string tableName = (string)_tableEnumerator.Current;
- _connectionPool.TryGetValue(tableName, out _currentTable);
- _configEnumerator = _currentTable.Keys.GetEnumerator();
- Debug.Assert(_configEnumerator != null, "Enumerator should not be null");
- continue;
- }
-
- break;
- }
-
- return false;
- }
-
- ///
- ///
- ///
- public void Reset()
- {
- _tableEnumerator.Reset();
- _currentTable = (ConcurrentDictionary>)_tableEnumerator.Current;
- _configEnumerator = _currentTable.Keys.GetEnumerator();
- _currentConnections = (ConcurrentDictionary)_configEnumerator.Current;
- _connectionEnumerator = _currentConnections.Keys.GetEnumerator();
- Guid key = (Guid)_connectionEnumerator.Current;
- _currentConnections.TryGetValue(key, out _currentConnection);
- }
-
- ///
- ///
- ///
- public object Current
- {
- get { return _currentConnection; }
- }
-
- ///
- ///
- ///
- ///
- public IEnumerator GetEnumerator()
- {
- return this;
- }
- }
-
- #endregion Connection Enumerator
-
- #region Disconnect/Reconnect
-
- private int _isReconnectServicing;
- private const long NotMarked = 0;
- private const long Marked = 1;
- private long _newConnectionMarked = NotMarked;
-
- private void CheckAndStartDisconnectReconnectThread()
- {
- if (_checkForDisconnect != CheckForDisconnect) return;
-
- if (Interlocked.CompareExchange(ref _isReconnectServicing, Servicing, NotServicing) != NotServicing) return;
-
- TraceThreadPoolInfo("Queuing user workitem disconnect/reconnect worker");
- ThreadPool.QueueUserWorkItem(DisconnectReconnectWorker);
- }
-
- ///
- /// Disconnect and reconnect to different runspaces as necessary
- /// so as to help the connection manager scale and run a large
- /// number of commands on a large number of remote nodes
- ///
- /// unused
- private void DisconnectReconnectWorker(object state)
- {
- if (_isDisposed || _isDisposing)
- {
- return;
- }
-
- TraceThreadPoolInfo("Running disconnect/reconnect worker");
-
- Interlocked.CompareExchange(ref _newConnectionMarked, NotMarked, Marked);
-
- while (Interlocked.CompareExchange(ref _newConnectionMarked, Marked, NotMarked) == Marked)
- {
- foreach (Connection connection in
- (new ConnectionEnumerator(_connectionPool)))
- {
- if (_disconnectedSessionCount > _maxDisconnectedSessions) break;
-
- if (!connection.Busy) continue;
- if (!connection.ReadyForDisconnect) continue;
-
- connection.DisconnectedIntentionally = true;
- // add a disconnect operation to the queue of operations
- SubmitOperation(new DisconnectOperation(connection));
- }
-
- // at this point all relevant connections have been disconnected
- // now connect to every remote connection for a specified period of time
-
- // only connections which were initially marked for disconnected
- // would have been disconnected
- foreach (Connection connection in
- (new ConnectionEnumerator(_connectionPool)))
- {
- if (_connectedSessionCount > _maxConnectedSessions) break;
-
- if (!connection.ReadyForReconnect) continue;
-
- connection.DisconnectedIntentionally = false;
- SubmitOperation(new ReconnectOperation(connection));
- }
- }
-
- _tracer.WriteMessage("PSW ConnMgr: Exiting disconnect reconnect worker");
- // reset flag that disconnect/reconnect thread is running
- Interlocked.CompareExchange(ref _isReconnectServicing, NotServicing, Servicing);
- }
-
- ///
- /// Callback to indicate that this runspace been initiated with
- /// a pipeline and can be disconnected
- ///
- /// runspace that needs to be marked as
- /// ready for disconnect
- public override void ReadyForDisconnect(Runspace runspace)
- {
- Connection connection = GetConnectionForRunspace(runspace);
- _tracer.WriteMessage("PSW ConnMgr: Runspace marked as ready for disconnect");
-
- // at this point connection will be not null
- // since GetConnectionForRunspace() should have
- // handled all cases and raised an exception
- Debug.Assert(connection != null, "GetConnectionForRunspace has not handled all cases and raised an exception");
-
- if (connection.Busy)
- {
- // mark the connection as ready for disconnect
- // the thread which is servicing disconnect and reconnect
- // will take care of disconnecting and reconnecting the same
- lock (_syncObject)
- {
- if (!connection.Busy)
- return;
-
- connection.ReadyForDisconnect = true;
- Interlocked.CompareExchange(ref _newConnectionMarked, NotMarked, Marked);
- }
-
- CheckAndStartRequiredThreads();
- }
- }
-
- #endregion Disconnect/Reconnect
-
- #region Test Helpers
-
- private readonly ManualResetEvent _testHelperCloseDone = new ManualResetEvent(false);
- internal void ClearAll()
- {
- if (_connectionPool.Count > 0)
- {
- _testHelperCloseDone.Reset();
-
- foreach (CloseOperation operation in
- from Connection connection in new ConnectionEnumerator(_connectionPool)
- select new CloseOperation(connection))
- {
- operation.OperationComplete += OperationComplete;
- SubmitOperation(operation);
- }
-
- _testHelperCloseDone.WaitOne();
-
- _connectionPool.Clear();
- }
- }
-
- private void OperationComplete(object sender, EventArgs e)
- {
- CloseOperation closeOperation = sender as CloseOperation;
- Debug.Assert(closeOperation != null, "CloseOperation not returned as sender");
- closeOperation.OperationComplete -= OperationComplete;
-
- if (_pendingQueue.Count == 0)
- {
- _testHelperCloseDone.Set();
- }
- }
-
- #endregion Test Helpers
- }
-}
diff --git a/src/Microsoft.PowerShell.Workflow.ServiceCore/ServiceCore/WorkflowCore/Constants.cs b/src/Microsoft.PowerShell.Workflow.ServiceCore/ServiceCore/WorkflowCore/Constants.cs
deleted file mode 100644
index 2d178f83bb..0000000000
--- a/src/Microsoft.PowerShell.Workflow.ServiceCore/ServiceCore/WorkflowCore/Constants.cs
+++ /dev/null
@@ -1,91 +0,0 @@
-/********************************************************************++
-Copyright (c) Microsoft Corporation. All rights reserved.
---********************************************************************/
-
-using System;
-using System.Reflection;
-using System.Collections.Generic;
-using System.Globalization;
-
-namespace Microsoft.PowerShell.Workflow
-{
- internal static class Constants
- {
-
- internal const string AsJob = "AsJob";
-
- // Remoting-related constants
- internal const string ComputerName = "PSComputerName";
- internal const string Credential = "PSCredential";
- internal const string Port = "PSPort";
- internal const string UseSSL = "PSUseSSL";
- internal const string ConfigurationName = "PSConfigurationName";
- internal const string ApplicationName = "PSApplicationName";
- internal const string ConnectionURI = "PSConnectionURI";
- internal const string AllowRedirection = "PSAllowRedirection";
- internal const string SessionOption = "PSSessionOption";
- internal const string Authentication = "PSAuthentication";
- internal const string AuthenticationLevel = "PSAuthenticationLevel";
- internal const string CertificateThumbprint = "PSCertificateThumbprint";
- internal const string PSParameterCollection = "PSParameterCollection";
- internal const string PSInputCollection = "PSInputCollection";
- internal const string InputObject = "InputObject";
- internal const string PSSenderInfo = "PSSenderInfo";
- internal const string PSCurrentDirectory = "PSCurrentDirectory";
- internal const string PSSuspendOnError = "PSSuspendOnError";
-
- // PowerShell-common constants
- internal const string Verbose = "Verbose";
- internal const string Debug = "Debug";
- internal const string ErrorAction = "ErrorAction";
- internal const string WarningAction = "WarningAction";
- internal const string InformationAction = "InformationAction";
- internal const string ErrorVariable = "ErrorVariable";
- internal const string WarningVariable = "WarningVariable";
- internal const string InformationVariable = "InformationVariable";
- internal const string OutVariable = "OutVariable";
- internal const string OutBuffer = "OutBuffer";
- internal const string PipelineVariable = "PipelineVariable";
-
- // Retry policy constants
- internal const string ConnectionRetryCount = "PSConnectionRetryCount";
- internal const string ActionRetryCount = "PSActionRetryCount";
- internal const string ConnectionRetryIntervalSec = "PSConnectionRetryIntervalSec";
- internal const string ActionRetryIntervalSec = "PSActionRetryIntervalSec";
-
- internal const string PrivateMetadata = "PSPrivateMetadata";
- internal const string WorkflowTakesPrivateMetadata = "WorkflowTakesPrivateMetadata";
- internal const string WorkflowJobCreationContext = "WorkflowJobCreationContext";
-
- // Timers
- internal const string PSRunningTime = "PSRunningTimeoutSec";
- internal const string PSElapsedTime = "PSElapsedTimeoutSec";
- internal const string Int32MaxValueDivideByThousand = "2147483";
-
- internal const string ModulePath = "PSWorkflowRoot";
- internal const string JobName = "JobName";
- internal const string DefaultComputerName = "localhost";
-
- // Job Metadata constants
- internal const string JobMetadataInstanceId = "InstanceId";
- internal const string JobMetadataSessionId = "Id";
- internal const string JobMetadataName = "Name";
- internal const string JobMetadataCommand = "Command";
- internal const string JobMetadataStateReason = "Reason";
- internal const string JobMetadataParentName = "ParentName";
- internal const string JobMetadataParentCommand = "ParentCommand";
- internal const string JobMetadataParentInstanceId = "ParentInstanceId";
- internal const string JobMetadataParentSessionId = "ParentSessionId";
- internal const string JobMetadataLocation = "Location";
- internal const string JobMetadataStatusMessage = "StatusMessage";
- internal const string JobMetadataUserName = "UserName";
- internal const string JobMetadataPid = "ProcessId";
- internal const string JobMetadataFilterState = "State";
-
- internal const string Persist = "PSPersist";
- internal const string PSRequiredModules = "PSRequiredModules";
-
- internal const string PSWorkflowErrorAction = "PSWorkflowErrorAction";
- internal const int MaxAllowedPersistencePathLength = 120;
- }
-}
diff --git a/src/Microsoft.PowerShell.Workflow.ServiceCore/ServiceCore/WorkflowCore/DefaultWorkflowSessionConfiguration.cs b/src/Microsoft.PowerShell.Workflow.ServiceCore/ServiceCore/WorkflowCore/DefaultWorkflowSessionConfiguration.cs
deleted file mode 100644
index e5bbab4a0c..0000000000
--- a/src/Microsoft.PowerShell.Workflow.ServiceCore/ServiceCore/WorkflowCore/DefaultWorkflowSessionConfiguration.cs
+++ /dev/null
@@ -1,126 +0,0 @@
-/********************************************************************++
- * Copyright (c) Microsoft Corporation. All rights reserved.
- * --********************************************************************/
-
-using System.Collections.ObjectModel;
-using System.IO;
-using System.Management.Automation.Remoting;
-using System;
-using System.Management.Automation;
-using System.Management.Automation.Runspaces;
-using System.Threading;
-using System.Management.Automation.Tracing;
-using System.Globalization;
-using Microsoft.PowerShell.Commands;
-
-namespace Microsoft.PowerShell.Workflow
-{
- ///
- /// Configuration for the M3P endpoint
- ///
- public class PSWorkflowSessionConfiguration : PSSessionConfiguration
- {
- ///
- /// IsWorkflowTypeEndpoint
- ///
- internal static bool IsWorkflowTypeEndpoint;
-
- #region Overrides of PSSessionConfiguration
-
- ///
- ///
- ///
- ///
- ///
- ///
- public override InitialSessionState GetInitialSessionState(PSSenderInfo senderInfo)
- {
- throw new NotImplementedException();
- }
-
- ///
- ///
- ///
- ///
- ///
- ///
- ///
- public override InitialSessionState GetInitialSessionState(PSSessionConfigurationData sessionConfigurationData, PSSenderInfo senderInfo, string configProviderId)
- {
- Tracer structuredTracer = new Tracer();
-
- structuredTracer.Correlate();
-
- if (sessionConfigurationData == null)
- throw new ArgumentNullException("sessionConfigurationData");
-
- if (senderInfo == null)
- throw new ArgumentNullException("senderInfo");
-
- if (string.IsNullOrEmpty(configProviderId))
- throw new ArgumentNullException("configProviderId");
-
- if (Interlocked.CompareExchange(ref _modulesLoaded, ModulesLoaded, ModulesNotLoaded) == ModulesNotLoaded)
- {
- // it is sufficient if Populate() is called the first time and
- // modules are loaded once
-
- try
- {
- IsWorkflowTypeEndpoint = true;
-
- PSWorkflowConfigurationProvider workflowConfiguration = WorkflowJobSourceAdapter.GetInstance().GetPSWorkflowRuntime().Configuration;
- if (workflowConfiguration == null)
- throw new InvalidOperationException("PSWorkflowConfigurationProvider is null");
-
- workflowConfiguration.Populate(sessionConfigurationData.PrivateData, configProviderId, senderInfo);
-
- // now get all the modules in the specified path and import the same
- if (sessionConfigurationData.ModulesToImport != null)
- {
- foreach (var module in sessionConfigurationData.ModulesToImport)
- {
- ModuleSpecification moduleSpec = null;
- if (ModuleSpecification.TryParse(module, out moduleSpec))
- {
- var modulesToImport = new Collection { moduleSpec };
- InitialSessionState.ImportPSModule(modulesToImport);
- }
- else
- {
- InitialSessionState.ImportPSModule(new[] { Environment.ExpandEnvironmentVariables(module) });
- }
- }
- }
-
- // Start the workflow job manager, if not started, to add an event handler for zero active sessions changed events
- // This is required to auto shutdown the workflow type shared process when no workflow jobs have scheduled/inprogress and when no active sessions
- WorkflowJobSourceAdapter.GetInstance().GetJobManager();
- }
- catch(Exception)
- {
- // if there is an exception in either Populate() or Importing modules
- // we consider that it is not loaded
- Interlocked.CompareExchange(ref _modulesLoaded, ModulesNotLoaded, ModulesLoaded);
- throw;
- }
- }
-
- if (configProviderId.ToLower(CultureInfo.InvariantCulture).Equals("http://schemas.microsoft.com/powershell/microsoft.windows.servermanagerworkflows"))
- {
- PSSessionConfigurationData.IsServerManager = true;
- }
-
- return InitialSessionState;
- }
-
- private static readonly InitialSessionState InitialSessionState =
- InitialSessionState.CreateRestricted(SessionCapabilities.WorkflowServer | SessionCapabilities.RemoteServer | SessionCapabilities.Language);
-
- private static int _modulesLoaded = ModulesNotLoaded;
- private const int ModulesNotLoaded = 0;
- private const int ModulesLoaded = 1;
-
- #endregion
- }
-}
diff --git a/src/Microsoft.PowerShell.Workflow.ServiceCore/ServiceCore/WorkflowCore/DefinitionCache.cs b/src/Microsoft.PowerShell.Workflow.ServiceCore/ServiceCore/WorkflowCore/DefinitionCache.cs
deleted file mode 100644
index 4bdcbc67c7..0000000000
--- a/src/Microsoft.PowerShell.Workflow.ServiceCore/ServiceCore/WorkflowCore/DefinitionCache.cs
+++ /dev/null
@@ -1,608 +0,0 @@
-//
-// Copyright (C) Microsoft. All rights reserved.
-//
-using System;
-using System.Activities;
-using System.Collections.Concurrent;
-using System.Collections.Generic;
-using System.Collections.ObjectModel;
-using System.Diagnostics;
-using System.Globalization;
-using System.IO;
-using System.Linq;
-using System.Management.Automation;
-using System.Management.Automation.Tracing;
-using Microsoft.PowerShell.Commands;
-using System.Reflection;
-
-namespace Microsoft.PowerShell.Workflow
-{
- internal sealed class DefinitionCache
- {
-
- #region Privates
-
- internal struct WorkflowDetails
- {
- internal Activity ActivityTree;
- internal string CompiledAssemblyPath;
- internal string CompiledAssemblyName;
- internal bool IsWindowsActivity;
- };
-
- private readonly PowerShellTraceSource _tracer = PowerShellTraceSourceFactory.GetTraceSource();
-
- ///
- /// Cache of workflow details. This is unbounded
- ///
- private readonly Dictionary _workflowDetailsCache =
- new Dictionary(new CompareBasedOnInstanceId());
-
- ///
- /// this is the cache of compiled activities which will be bounded
- ///
- /// this is separate since Opalis will not use our cache
- private readonly ConcurrentDictionary _cachedActivities =
- new ConcurrentDictionary(new CompareBasedOnInstanceId());
-
- private System.Timers.Timer _cleanupTimer;
- private int activitiesCleanupIntervalMSec;
-
- private static readonly DefinitionCache _instance = new DefinitionCache();
-
- private DefinitionCache()
- {
- activitiesCleanupIntervalMSec = WorkflowJobSourceAdapter.GetInstance().GetPSWorkflowRuntime().Configuration.ActivitiesCacheCleanupIntervalMSec;
-
- _cleanupTimer = new System.Timers.Timer(activitiesCleanupIntervalMSec);
- _cleanupTimer.Elapsed += HandleCleanupTimerElapsed;
- _cleanupTimer.AutoReset = false;
- _cleanupTimer.Start();
- }
-
- private void HandleCleanupTimerElapsed(object sender, System.Timers.ElapsedEventArgs e)
- {
- List activitiesToRemove = new List();
- Activity activity;
-
- foreach (var workflowJobDefinition in _cachedActivities.Keys)
- {
- if ((GetRuntimeAssemblyPath(workflowJobDefinition) == null) &&
- (DateTime.Now - workflowJobDefinition.LastUsedDateTime > TimeSpan.FromMilliseconds(activitiesCleanupIntervalMSec)))
- {
- activitiesToRemove.Add(workflowJobDefinition);
- }
- }
-
- foreach (var wfJobDefinition in activitiesToRemove)
- {
- _cachedActivities.TryRemove(wfJobDefinition, out activity);
- }
-
- // Schedule the next cleanup
- _cleanupTimer.Start();
- }
-
- ///
- /// Cache size
- ///
- private const int _cacheSize = 1000;
-
- ///
- /// Path to Windows folder
- ///
- private const string WindowsPath = "%windir%\\system32";
-
- #endregion Privates
-
- #region Internal
-
- internal int CacheSize
- {
- get { return _cacheSize; }
- }
-
- ///
- /// Return the singleton instance.
- ///
- internal static DefinitionCache Instance
- {
- get
- {
- return _instance;
- }
- }
-
- internal JobDefinition GetDefinition(Guid instanceId)
- {
- return _workflowDetailsCache.Keys.FirstOrDefault(def => def.InstanceId == instanceId);
- }
-
- internal string GetWorkflowXaml(WorkflowJobDefinition definition)
- {
- return definition.Xaml;
- }
-
- internal string GetRuntimeAssemblyPath(WorkflowJobDefinition definition)
- {
- WorkflowDetails workflowDetail;
-
- return _workflowDetailsCache.TryGetValue(definition, out workflowDetail) ? workflowDetail.CompiledAssemblyPath : null;
- }
-
- internal string GetRuntimeAssemblyName(WorkflowJobDefinition definition)
- {
- WorkflowDetails workflowDetail;
-
- return _workflowDetailsCache.TryGetValue(definition, out workflowDetail) ? workflowDetail.CompiledAssemblyName : null;
- }
-
- internal bool AllowExternalActivity;
-
- ///
- /// Compiles the activity and adds it to the cache before returning it.
- ///
- /// WorkflowJobDefinition defined to represent a compiled activity.
- /// Activity Tree used for external activities
- ///
- /// indicates if the specified xaml is a Windows workflow
- /// Optional, once assigned, only root Workflow will be compiled
- /// Activity compiled from xaml given, or retrieved from cache.
- /// Null if not found.
- internal Activity CompileActivityAndSaveInCache(WorkflowJobDefinition definition, Activity activityTree, Dictionary requiredAssemblies, out bool windowsWorkflow, string rootWorkflowName = null)
- {
- WorkflowDetails workflowDetail = new WorkflowDetails();
- Activity activity = null;
-
- // initialize windows workflow to false
- windowsWorkflow = false;
-
- string resultingCompiledAssemblyPath = definition.DependentAssemblyPath;
- string modulePath = definition.ModulePath;
- string[] dependentWorkflows = definition.DependentWorkflows.ToArray();
- Assembly resultingCompiledAssembly = null;
- string resultingCompiledAssemblyName = null;
- string xaml = definition.Xaml;
-
- if (activityTree != null)
- {
- _tracer.WriteMessage(string.Format(CultureInfo.InvariantCulture,
- "DefinitionCache: Caching activity for definition with instance ID: {0}. The activity Tree is passed.",
- definition.InstanceId));
- workflowDetail.ActivityTree = activityTree;
- activity = activityTree;
- }
- else if (!String.IsNullOrEmpty(xaml))
- {
- // we need to read the xaml from the specified path and compile the same
- _tracer.WriteMessage(string.Format(CultureInfo.InvariantCulture,
- "DefinitionCache: Caching activity for definition with instance ID: {0}. Xaml is passed",
- definition.InstanceId));
-
- workflowDetail.ActivityTree = null;
- // check if specified workflow is a windows workflow
- if (!string.IsNullOrEmpty(modulePath))
- {
- string resolvedPath = Environment.ExpandEnvironmentVariables(modulePath);
- string resolvedWindowsPath = Environment.ExpandEnvironmentVariables(WindowsPath);
- if (resolvedPath.IndexOf(resolvedWindowsPath, StringComparison.CurrentCultureIgnoreCase) != -1)
- {
- windowsWorkflow = true;
- }
- }
-
- if (definition.DependentAssemblyPath == null && dependentWorkflows.Length == 0)
- {
- activity = ImportWorkflowCommand.ConvertXamlToActivity(xaml);
- }
- else
- {
- if (rootWorkflowName == null || (definition.Command == rootWorkflowName))
- {
- activity = ImportWorkflowCommand.ConvertXamlToActivity(xaml, dependentWorkflows,
- requiredAssemblies,
- ref resultingCompiledAssemblyPath,
- ref resultingCompiledAssembly,
- ref resultingCompiledAssemblyName);
- }
- else
- {
- activity = ImportWorkflowCommand.ConvertXamlToActivity(xaml);
- }
- }
- }
-
- if (activity != null)
- {
- workflowDetail.IsWindowsActivity = windowsWorkflow;
- workflowDetail.CompiledAssemblyPath = resultingCompiledAssemblyPath;
- workflowDetail.CompiledAssemblyName = resultingCompiledAssemblyName;
-
- lock (_syncObject)
- {
- WorkflowJobDefinition definitionToRemove =
- _workflowDetailsCache.Keys.FirstOrDefault(item => item.InstanceId == definition.InstanceId);
- if (definitionToRemove != null)
- _workflowDetailsCache.Remove(definition);
-
- _workflowDetailsCache.Add(definition, workflowDetail);
- }
-
- // If cached activity count reaches _cacheSize,
- // Removing the cached activity at index 0 and adding the new activity to the activity cache,
- // Old logic was to clear 1000 cached activities and recompiling them again when needed.
- //
- if (_cachedActivities.Count == _cacheSize)
- {
- Activity removedActivity;
- _cachedActivities.TryRemove(_cachedActivities.Keys.ElementAt(0), out removedActivity);
- }
-
- _cachedActivities.TryAdd(definition, activity);
-
- return activity;
- }
-
- // we should never hit this point under normal course of operations
- return null;
- }
-
- ///
- ///
- ///
- ///
- ///
- ///
- internal Activity GetActivityFromCache(WorkflowJobDefinition definition, out bool windowsWorkflow)
- {
- Activity activity = null;
- WorkflowDetails workflowDetail;
-
- // initialize windowsWorkflow to false
- windowsWorkflow = false;
- if (_workflowDetailsCache.TryGetValue(definition, out workflowDetail))
- {
- // if there is a workflow activity we would have already computed whether it is a
- // Windows workflow, set the same
- windowsWorkflow = workflowDetail.IsWindowsActivity;
-
- if (workflowDetail.ActivityTree != null)
- {
- if (!AllowExternalActivity)
- {
- Debug.Assert(false, "Product code should not contain passing an activity to definition cache");
- }
-
- activity = workflowDetail.ActivityTree;
- }
-
- // if a cached value is available return the same
- _cachedActivities.TryGetValue(definition, out activity);
- if (activity == null)
- {
- // if activity is not available in cache recompile using info in
- // definition cache
- activity = CompileActivityAndSaveInCache(definition, null, null, out windowsWorkflow);
- }
-
- definition.LastUsedDateTime = DateTime.Now;
- }
-
- return activity;
- }
-
- ///
- ///
- ///
- ///
- ///
- ///
- internal Activity GetActivityFromCache(string xaml, out WorkflowJobDefinition workflowJobDefinition)
- {
- workflowJobDefinition = null;
-
- foreach (var definition in
- _workflowDetailsCache.Keys.Where(definition => string.Equals(definition.Xaml, xaml, StringComparison.OrdinalIgnoreCase)))
- {
- bool windowsWorkflow;
- workflowJobDefinition = definition;
- return GetActivityFromCache(definition, out windowsWorkflow);
- }
-
- return null;
- }
-
- private readonly object _syncObject = new object();
-
- #endregion Internal
-
- #region Test Helpers
-
- internal Dictionary WorkflowDetailsCache
- {
- get { return _workflowDetailsCache; }
- }
-
- internal ConcurrentDictionary ActivityCache
- {
- get { return _cachedActivities; }
- }
-
- internal void ClearAll()
- {
- _workflowDetailsCache.Clear();
- _cachedActivities.Clear();
- }
-
- // only called from test
- internal Activity GetActivity(Guid instanceId)
- {
- WorkflowJobDefinition workflowJobDefinition = new WorkflowJobDefinition(typeof(WorkflowJobSourceAdapter),
- string.Empty, string.Empty,
- string.Empty,
- WorkflowJobDefinition.EmptyEnumerable,
- string.Empty, null, string.Empty) { InstanceId = instanceId };
-
- bool windowsWorkflow;
- Activity activity = GetActivityFromCache(workflowJobDefinition, out windowsWorkflow) ??
- CompileActivityAndSaveInCache(workflowJobDefinition, null, null, out windowsWorkflow);
-
- return activity;
- }
-
- //only called from test
- internal Activity GetActivity(JobDefinition definition, string xaml)
- {
- bool windowsWorkflow;
- WorkflowJobDefinition workflowJobDefinition = new WorkflowJobDefinition(definition, string.Empty,
- WorkflowJobDefinition.EmptyEnumerable,
- string.Empty,
- xaml);
- Activity activity = GetActivityFromCache(workflowJobDefinition, out windowsWorkflow) ??
- CompileActivityAndSaveInCache(workflowJobDefinition, null, null, out windowsWorkflow);
-
- return activity;
- }
-
- //only called from test
- internal Activity GetActivity(JobDefinition definition, string xaml, string[] dependentWorkflows)
- {
- bool windowsWorkflow;
- WorkflowJobDefinition workflowJobDefinition = new WorkflowJobDefinition(definition, string.Empty,
- dependentWorkflows ?? WorkflowJobDefinition.EmptyEnumerable,
- string.Empty,
- xaml);
-
- Activity activity = GetActivityFromCache(workflowJobDefinition, out windowsWorkflow) ??
- CompileActivityAndSaveInCache(workflowJobDefinition, null, null, out windowsWorkflow);
-
- return activity;
- }
-
- internal Activity GetActivity(JobDefinition definition, out bool windowsWorkflow)
- {
- WorkflowJobDefinition workflowJobDefinition = new WorkflowJobDefinition(definition);
-
- Activity activity = GetActivityFromCache(workflowJobDefinition, out windowsWorkflow) ??
- CompileActivityAndSaveInCache(workflowJobDefinition, null, null, out windowsWorkflow);
-
- return activity;
- }
-
- ///
- /// Remove a cached definition. Needed when functions are removed to release resources.
- ///
- /// Xaml definition to remove.
- /// True if succeeded.
- internal bool RemoveCachedActivity(JobDefinition definition)
- {
- Debug.Assert(definition != null);
-
- WorkflowJobDefinition workflowJobDefinition = new WorkflowJobDefinition(definition);
- Activity activity;
- _cachedActivities.TryRemove(workflowJobDefinition, out activity);
- lock (_syncObject)
- {
- if (_workflowDetailsCache.ContainsKey(workflowJobDefinition))
- {
- return _workflowDetailsCache.Remove(workflowJobDefinition);
- }
- }
- return false;
- }
-
- internal bool RemoveCachedActivity(Guid instanceId)
- {
- var definition = new JobDefinition(null, null, null);
- definition.InstanceId = instanceId;
- return RemoveCachedActivity(definition);
- }
-
- #endregion Test Helpers
- }
-
- internal class CompareBasedOnInstanceId : IEqualityComparer
- {
- #region IEqualityComparer Members
-
- public bool Equals(WorkflowJobDefinition x, WorkflowJobDefinition y)
- {
- return x.InstanceId == y.InstanceId;
- }
-
- public int GetHashCode(WorkflowJobDefinition obj)
- {
- return obj.InstanceId.GetHashCode();
- }
-
- #endregion
- }
-
- internal class CompareBasedOnCommand : IEqualityComparer
- {
- #region IEqualityComparer Members
-
- public bool Equals(WorkflowJobDefinition x, WorkflowJobDefinition y)
- {
- bool returnValue = false;
-
- if (String.Equals(y.ModulePath, x.ModulePath, StringComparison.OrdinalIgnoreCase))
- {
- if (string.Equals(y.Command, x.Command, StringComparison.OrdinalIgnoreCase))
- {
- returnValue = true;
- }
- }
-
- return returnValue;
- }
-
- public int GetHashCode(WorkflowJobDefinition obj)
- {
- int hashCode = 0;
- string moduleQualifiedCommand = string.Empty;
-
- if (!string.IsNullOrEmpty(obj.ModulePath))
- moduleQualifiedCommand += obj.ModulePath;
-
- if (!string.IsNullOrEmpty(obj.Command))
- moduleQualifiedCommand += obj.Command;
-
- hashCode = moduleQualifiedCommand.GetHashCode();
-
- return hashCode;
- }
-
- private static readonly CompareBasedOnCommand Comparer = new CompareBasedOnCommand();
- internal static bool Compare(WorkflowJobDefinition x, WorkflowJobDefinition y)
- {
- return Comparer.Equals(x, y);
- }
-
- #endregion
- }
-
- internal class WorkflowJobDefinition : JobDefinition
- {
- ///
- ///
- ///
- ///
- ///
- ///
- public WorkflowJobDefinition(Type jobSourceAdapterType, string command, string name) : base(jobSourceAdapterType, command, name)
- {
- IsScriptWorkflow = false;
- }
-
- internal WorkflowJobDefinition(Type jobSourceAdapterType, string command, string name, string modulePath,
- IEnumerable dependentWorkflows, string dependentAssemblyPath, Dictionary requiredAssemblies, string xaml)
- : this(jobSourceAdapterType, command, name)
- {
- _modulePath = modulePath;
- _dependentAssemblyPath = dependentAssemblyPath;
- _dependentWorkflows.AddRange(dependentWorkflows);
- _requiredAssemblies = requiredAssemblies;
- _xaml = xaml;
- _lastUsedDateTime = DateTime.Now;
- }
-
- internal WorkflowJobDefinition(JobDefinition jobDefinition, string modulePath,
- IEnumerable dependentWorkflows, string dependentAssemblyPath, string xaml)
- : this(jobDefinition.JobSourceAdapterType, jobDefinition.Command, jobDefinition.Name, modulePath, dependentWorkflows, dependentAssemblyPath, null, xaml)
- {
- InstanceId = jobDefinition.InstanceId;
- }
-
- internal WorkflowJobDefinition(JobDefinition jobDefinition)
- :this(jobDefinition, string.Empty, EmptyEnumerable, string.Empty, string.Empty)
- {
-
- }
-
- private readonly string _modulePath;
- internal string ModulePath
- {
- get { return _modulePath; }
- }
-
- private readonly List _dependentWorkflows = new List();
- internal List DependentWorkflows
- {
- get { return _dependentWorkflows; }
- }
-
- private readonly string _dependentAssemblyPath;
- internal string DependentAssemblyPath
- {
- get { return _dependentAssemblyPath; }
- }
-
- private readonly Dictionary _requiredAssemblies;
- internal Dictionary RequiredAssemblies
- {
- get { return _requiredAssemblies; }
- }
-
- private readonly string _xaml;
- internal string Xaml
- {
- get { return _xaml; }
- }
-
- internal bool IsScriptWorkflow { get; set; }
-
- internal static IEnumerable EmptyEnumerable = new Collection();
-
- private DateTime _lastUsedDateTime;
- internal DateTime LastUsedDateTime
- {
- get { return _lastUsedDateTime; }
- set { _lastUsedDateTime = value; }
- }
-
- ///
- /// Returns the same object is the specified job definition is a
- /// WorkflowJobDefinition. If not creates a new one and assigns
- /// the same
- ///
- /// job definition to check
- /// WorkflowJobDefinition equivalent
- internal static WorkflowJobDefinition AsWorkflowJobDefinition(JobDefinition definition)
- {
- return definition as WorkflowJobDefinition ??
- (DefinitionCache.Instance.GetDefinition(definition.InstanceId) as WorkflowJobDefinition ??
- new WorkflowJobDefinition(definition));
- }
-
- ///
- ///
- ///
- ///
- ///
- public override void GetObjectData(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context)
- {
- base.GetObjectData(info, context);
-
- throw new NotImplementedException();
- }
-
- ///
- /// Workflow script file name or null if no associated file.
- ///
- internal string WorkflowScriptFile
- {
- get;
- set;
- }
-
- ///
- /// Full workflow script source.
- ///
- internal string WorkflowFullScript
- {
- get;
- set;
- }
- }
-}
diff --git a/src/Microsoft.PowerShell.Workflow.ServiceCore/ServiceCore/WorkflowCore/FileInstanceStore/AsyncResult.cs b/src/Microsoft.PowerShell.Workflow.ServiceCore/ServiceCore/WorkflowCore/FileInstanceStore/AsyncResult.cs
deleted file mode 100644
index 2c04a68721..0000000000
--- a/src/Microsoft.PowerShell.Workflow.ServiceCore/ServiceCore/WorkflowCore/FileInstanceStore/AsyncResult.cs
+++ /dev/null
@@ -1,174 +0,0 @@
-/********************************************************************++
-Copyright (c) Microsoft Corporation. All rights reserved.
---********************************************************************/
-
-namespace Microsoft.PowerShell.Workflow
-{
- using System;
- using System.Diagnostics;
- using System.Threading;
-
- ///
- /// A generic base class for IAsyncResult implementations
- /// that wraps a ManualResetEvent.
- ///
- abstract class FileStoreAsyncResult : IAsyncResult
- {
- AsyncCallback callback;
- object state;
- bool completedSynchronously;
- bool endCalled;
- Exception exception;
- bool isCompleted;
- ManualResetEvent manualResetEvent;
- object thisLock;
-
- protected FileStoreAsyncResult(AsyncCallback callback, object state)
- {
- this.callback = callback;
- this.state = state;
- this.thisLock = new object();
- }
-
- public object AsyncState
- {
- get
- {
- return state;
- }
- }
-
- public WaitHandle AsyncWaitHandle
- {
- get
- {
- if (manualResetEvent != null)
- {
- return manualResetEvent;
- }
-
- lock (ThisLock)
- {
- if (manualResetEvent == null)
- {
- manualResetEvent = new ManualResetEvent(isCompleted);
- }
- }
-
- return manualResetEvent;
- }
- }
-
- public bool CompletedSynchronously
- {
- get
- {
- return completedSynchronously;
- }
- }
-
- public bool IsCompleted
- {
- get
- {
- return isCompleted;
- }
- }
-
- object ThisLock
- {
- get
- {
- return this.thisLock;
- }
- }
-
- // Call this version of complete when your asynchronous operation is complete. This will update the state
- // of the operation and notify the callback.
- protected void Complete(bool completedSynchronously)
- {
- if (isCompleted)
- {
- // It is a bug to call Complete twice.
- throw new InvalidOperationException(Resources.AsyncResultAlreadyCompleted);
- }
-
- this.completedSynchronously = completedSynchronously;
-
- if (completedSynchronously)
- {
- // If we completedSynchronously, then there is no chance that the manualResetEvent was created so
- // we do not need to worry about a race condition.
- Debug.Assert(this.manualResetEvent == null, "No ManualResetEvent should be created for a synchronous AsyncResult.");
- this.isCompleted = true;
- }
- else
- {
- lock (ThisLock)
- {
- this.isCompleted = true;
- if (this.manualResetEvent != null)
- {
- this.manualResetEvent.Set();
- }
- }
- }
-
- // If the callback throws, there is a bug in the callback implementation
- if (callback != null)
- {
- callback(this);
- }
- }
-
- // Call this version of complete if you raise an exception during processing. In addition to notifying
- // the callback, it will capture the exception and store it to be thrown during AsyncResult.End.
- protected void Complete(bool completedSynchronously, Exception exception)
- {
- this.exception = exception;
- Complete(completedSynchronously);
- }
-
- // End should be called when the End function for the asynchronous operation is complete. It
- // ensures the asynchronous operation is complete, and does some common validation.
- protected static TAsyncResult End(IAsyncResult result)
- where TAsyncResult : FileStoreAsyncResult
- {
- if (result == null)
- {
- throw new ArgumentNullException("result");
- }
-
- TAsyncResult asyncResult = result as TAsyncResult;
-
- if (asyncResult == null)
- {
- throw new ArgumentException(Resources.InvalidAsyncResult);
- }
-
- if (asyncResult.endCalled)
- {
- throw new InvalidOperationException(Resources.AsyncResultAlreadyEnded);
- }
-
- asyncResult.endCalled = true;
-
- if (!asyncResult.isCompleted)
- {
- asyncResult.AsyncWaitHandle.WaitOne();
- }
-
- if (asyncResult.manualResetEvent != null)
- {
- asyncResult.manualResetEvent.Close();
- }
-
- if (asyncResult.exception != null)
- {
- throw asyncResult.exception;
- }
-
- return asyncResult;
- }
- }
-}
diff --git a/src/Microsoft.PowerShell.Workflow.ServiceCore/ServiceCore/WorkflowCore/FileInstanceStore/FileInstanceStore.cs b/src/Microsoft.PowerShell.Workflow.ServiceCore/ServiceCore/WorkflowCore/FileInstanceStore/FileInstanceStore.cs
deleted file mode 100644
index 0f95d8ec8b..0000000000
--- a/src/Microsoft.PowerShell.Workflow.ServiceCore/ServiceCore/WorkflowCore/FileInstanceStore/FileInstanceStore.cs
+++ /dev/null
@@ -1,225 +0,0 @@
-/********************************************************************++
-Copyright (c) Microsoft Corporation. All rights reserved.
---********************************************************************/
-
-namespace Microsoft.PowerShell.Workflow
-{
- using System;
- using System.Runtime.DurableInstancing;
- using System.Activities.DurableInstancing;
- using System.Collections.Generic;
- using System.Xml.Linq;
- using System.IO;
- using System.Xml;
- using System.Management.Automation.Tracing;
- using System.Activities.Persistence;
-
- internal class FileInstanceStore : InstanceStore
- {
- private static readonly Tracer StructuredTracer = new Tracer();
-
- private readonly PSWorkflowFileInstanceStore _stores;
- internal FileInstanceStore(PSWorkflowFileInstanceStore stores)
- {
- _stores = stores;
- }
-
- protected override IAsyncResult BeginTryCommand(InstancePersistenceContext context, InstancePersistenceCommand command, TimeSpan timeout, AsyncCallback callback, object state)
- {
- StructuredTracer.Correlate();
-
- try
- {
- if (command is SaveWorkflowCommand)
- {
- return new TypedCompletedAsyncResult(SaveWorkflow(context, (SaveWorkflowCommand)command), callback, state);
- }
- else if (command is LoadWorkflowCommand)
- {
- return new TypedCompletedAsyncResult(LoadWorkflow(context, (LoadWorkflowCommand)command), callback, state);
- }
- else if (command is CreateWorkflowOwnerCommand)
- {
- return new TypedCompletedAsyncResult(CreateWorkflowOwner(context, (CreateWorkflowOwnerCommand)command), callback, state);
- }
- else if (command is DeleteWorkflowOwnerCommand)
- {
- return new TypedCompletedAsyncResult(DeleteWorkflowOwner(context, (DeleteWorkflowOwnerCommand)command), callback, state);
- }
- return new TypedCompletedAsyncResult(false, callback, state);
- }
- catch (Exception e)
- {
- return new TypedCompletedAsyncResult(e, callback, state);
- }
- }
-
- protected override bool EndTryCommand(IAsyncResult result)
- {
- StructuredTracer.Correlate();
-
- TypedCompletedAsyncResult exceptionResult = result as TypedCompletedAsyncResult;
- if (exceptionResult != null)
- {
- throw exceptionResult.Data;
- }
- return TypedCompletedAsyncResult.End(result);
- }
-
- private bool SaveWorkflow(InstancePersistenceContext context, SaveWorkflowCommand command)
- {
- if (context.InstanceVersion == -1)
- {
- context.BindAcquiredLock(0);
- }
-
- if (command.CompleteInstance)
- {
- context.CompletedInstance();
- }
- else
- {
- string instanceType = "";
-
- const string InstanceTypeXName = "{urn:schemas-microsoft-com:System.Runtime.DurableInstancing/4.0/metadata}InstanceType";
- InstanceValue instanceTypeInstanceValue;
- if (command.InstanceMetadataChanges.TryGetValue(InstanceTypeXName, out instanceTypeInstanceValue))
- {
- instanceType = instanceTypeInstanceValue.Value.ToString();
- }
-
- Dictionary fullInstanceData = new Dictionary();
- fullInstanceData.Add("instanceId", context.InstanceView.InstanceId);
- fullInstanceData.Add("instanceOwnerId", context.InstanceView.InstanceOwner.InstanceOwnerId);
- fullInstanceData.Add("instanceData", SerializeablePropertyBag(command.InstanceData));
- fullInstanceData.Add("instanceMetadata", SerializeInstanceMetadata(context, command));
-
- foreach (KeyValuePair property in command.InstanceMetadataChanges)
- {
- context.WroteInstanceMetadataValue(property.Key, property.Value);
- }
-
- context.PersistedInstance(command.InstanceData);
-
- _stores.Save(WorkflowStoreComponents.Definition
- | WorkflowStoreComponents.Metadata
- | WorkflowStoreComponents.Streams
- | WorkflowStoreComponents.TerminatingError
- | WorkflowStoreComponents.Timer
- | WorkflowStoreComponents.ActivityState
- | WorkflowStoreComponents.JobState,
- fullInstanceData);
-
- }
-
- return true;
- }
-
- private bool LoadWorkflow(InstancePersistenceContext context, LoadWorkflowCommand command)
- {
- if (command.AcceptUninitializedInstance)
- {
- return false;
- }
-
- if (context.InstanceVersion == -1)
- {
- context.BindAcquiredLock(0);
- }
-
- Guid instanceId = context.InstanceView.InstanceId;
- Guid instanceOwnerId = context.InstanceView.InstanceOwner.InstanceOwnerId;
-
- IDictionary instanceData = null;
- IDictionary instanceMetadata = null;
-
- Dictionary fullInstanceData = _stores.LoadWorkflowContext();
-
- instanceData = this.DeserializePropertyBag((Dictionary)fullInstanceData["instanceData"]);
- instanceMetadata = this.DeserializePropertyBag((Dictionary)fullInstanceData["instanceMetadata"]);
-
- context.LoadedInstance(InstanceState.Initialized, instanceData, instanceMetadata, null, null);
-
- return true;
- }
-
- private bool CreateWorkflowOwner(InstancePersistenceContext context, CreateWorkflowOwnerCommand command)
- {
- Guid instanceOwnerId = Guid.NewGuid();
- context.BindInstanceOwner(instanceOwnerId, instanceOwnerId);
- context.BindEvent(HasRunnableWorkflowEvent.Value);
- return true;
- }
-
- private bool DeleteWorkflowOwner(InstancePersistenceContext context, DeleteWorkflowOwnerCommand command)
- {
- return true;
- }
-
- private Dictionary SerializeablePropertyBag(IDictionary source)
- {
- Dictionary scratch = new Dictionary();
- foreach (KeyValuePair property in source)
- {
- bool writeOnly = (property.Value.Options & InstanceValueOptions.WriteOnly) != 0;
-
- if (!writeOnly && !property.Value.IsDeletedValue)
- {
- scratch.Add(property.Key, property.Value.Value);
- }
- }
-
- return scratch;
- }
- private Dictionary SerializeInstanceMetadata(InstancePersistenceContext context, SaveWorkflowCommand command)
- {
- Dictionary metadata = null;
-
- foreach (var property in command.InstanceMetadataChanges)
- {
- if (!property.Value.Options.HasFlag(InstanceValueOptions.WriteOnly))
- {
- if (metadata == null)
- {
- metadata = new Dictionary();
- // copy current metadata. note that we must rid of InstanceValue as it is not properly serializeable
- foreach (var m in context.InstanceView.InstanceMetadata)
- {
- metadata.Add(m.Key, m.Value.Value);
- }
- }
-
- if (metadata.ContainsKey(property.Key))
- {
- if (property.Value.IsDeletedValue) metadata.Remove(property.Key);
- else metadata[property.Key] = property.Value.Value;
- }
- else
- {
- if (!property.Value.IsDeletedValue) metadata.Add(property.Key, property.Value.Value);
- }
- }
- }
-
- if (metadata == null)
- metadata = new Dictionary();
-
- return metadata;
- }
-
- private IDictionary DeserializePropertyBag(Dictionary source)
- {
- Dictionary destination = new Dictionary();
-
- foreach (KeyValuePair property in source)
- {
- destination.Add(property.Key, new InstanceValue(property.Value));
- }
-
- return destination;
- }
-
-
- }
-}
-
\ No newline at end of file
diff --git a/src/Microsoft.PowerShell.Workflow.ServiceCore/ServiceCore/WorkflowCore/FileInstanceStore/InstanceStoreCryptography.cs b/src/Microsoft.PowerShell.Workflow.ServiceCore/ServiceCore/WorkflowCore/FileInstanceStore/InstanceStoreCryptography.cs
deleted file mode 100644
index 0f7bafaf63..0000000000
--- a/src/Microsoft.PowerShell.Workflow.ServiceCore/ServiceCore/WorkflowCore/FileInstanceStore/InstanceStoreCryptography.cs
+++ /dev/null
@@ -1,68 +0,0 @@
-/********************************************************************++
-Copyright (c) Microsoft Corporation. All rights reserved.
---********************************************************************/
-
-namespace Microsoft.PowerShell.Workflow
-{
- using System;
- using System.IO;
- using System.Security.Cryptography;
- using System.Management.Automation.Tracing;
-
- ///
- /// This class implements the encrypt and decrypt functionality.
- ///
- internal class InstanceStoreCryptography
- {
- ///
- /// Tracer initialization.
- ///
- private static readonly PowerShellTraceSource Tracer = PowerShellTraceSourceFactory.GetTraceSource();
-
- ///
- /// The additional entry for security 'POWERSHELLWORKFLOW'
- ///
- private static byte[] s_additionalEntropy = { (byte)'P', (byte)'O', (byte)'W', (byte)'E', (byte)'R', (byte)'S', (byte)'H', (byte)'E', (byte)'L', (byte)'L', (byte)'W', (byte)'O', (byte)'R', (byte)'K', (byte)'F', (byte)'L', (byte)'O', (byte)'W' };
-
- ///
- /// Protect the data.
- ///
- /// The input data for encryption.
- /// Returns encrypted data.
- internal static byte[] Protect(byte[] data)
- {
- try
- {
- // Encrypt the data using DataProtectionScope.CurrentUser. The result can be decrypted
- // only by the same current user.
- return ProtectedData.Protect(data, s_additionalEntropy, DataProtectionScope.CurrentUser);
- }
- catch (CryptographicException e)
- {
- Tracer.TraceException(e);
-
- throw e;
- }
- }
-
- ///
- /// Unprotect data the encrypted data.
- ///
- /// Encrypted data.
- /// Returns decrypted data.
- internal static byte[] Unprotect(byte[] data)
- {
- try
- {
- return ProtectedData.Unprotect(data, s_additionalEntropy, DataProtectionScope.CurrentUser);
- }
- catch (CryptographicException e)
- {
- Tracer.TraceException(e);
-
- throw e;
- }
-
- }
- }
-}
diff --git a/src/Microsoft.PowerShell.Workflow.ServiceCore/ServiceCore/WorkflowCore/FileInstanceStore/InstanceStorePermission.cs b/src/Microsoft.PowerShell.Workflow.ServiceCore/ServiceCore/WorkflowCore/FileInstanceStore/InstanceStorePermission.cs
deleted file mode 100644
index 0d29a001b0..0000000000
--- a/src/Microsoft.PowerShell.Workflow.ServiceCore/ServiceCore/WorkflowCore/FileInstanceStore/InstanceStorePermission.cs
+++ /dev/null
@@ -1,44 +0,0 @@
-/********************************************************************++
-Copyright (c) Microsoft Corporation. All rights reserved.
---********************************************************************/
-
-namespace Microsoft.PowerShell.Workflow
-{
- using System;
- using System.IO;
- using System.Security.Cryptography;
- using System.Management.Automation.Tracing;
- using System.Security.AccessControl;
- using System.Security.Principal;
-
- ///
- /// This class implements the encrypt and decrypt functionality.
- ///
- internal class InstanceStorePermission
- {
- internal static void SetDirectoryPermissions(string folderName)
- {
- string account = WindowsIdentity.GetCurrent().Name;
- RemoveInheritablePermissions(folderName);
- AddDirectorySecurity(folderName, account, FileSystemRights.Modify, InheritanceFlags.ContainerInherit | InheritanceFlags.ObjectInherit, PropagationFlags.None, AccessControlType.Allow);
- }
-
- private static void AddDirectorySecurity(string folderName, string account, FileSystemRights rights, InheritanceFlags inheritance, PropagationFlags propagation, AccessControlType controlType)
- {
- DirectoryInfo info = new DirectoryInfo(folderName);
- DirectorySecurity dSecurity = info.GetAccessControl();
- dSecurity.AddAccessRule(new FileSystemAccessRule(account, rights, inheritance, propagation, controlType));
- info.SetAccessControl(dSecurity);
- }
-
- private static void RemoveInheritablePermissions(string folderName)
- {
- DirectoryInfo info = new DirectoryInfo(folderName);
- DirectorySecurity dSecurity = info.GetAccessControl();
- const bool IsProtected = true;
- const bool PreserveInheritance = false;
- dSecurity.SetAccessRuleProtection(IsProtected, PreserveInheritance);
- info.SetAccessControl(dSecurity);
- }
- }
-}
diff --git a/src/Microsoft.PowerShell.Workflow.ServiceCore/ServiceCore/WorkflowCore/FileInstanceStore/TypedAsyncResult.cs b/src/Microsoft.PowerShell.Workflow.ServiceCore/ServiceCore/WorkflowCore/FileInstanceStore/TypedAsyncResult.cs
deleted file mode 100644
index dd3a3d2e1e..0000000000
--- a/src/Microsoft.PowerShell.Workflow.ServiceCore/ServiceCore/WorkflowCore/FileInstanceStore/TypedAsyncResult.cs
+++ /dev/null
@@ -1,41 +0,0 @@
-/********************************************************************++
-Copyright (c) Microsoft Corporation. All rights reserved.
---********************************************************************/
-
-namespace Microsoft.PowerShell.Workflow
-{
- using System;
- using System.Diagnostics;
- using System.Threading;
-
- ///
- /// A strongly typed AsyncResult.
- ///
- ///
- abstract class TypedAsyncResult : FileStoreAsyncResult
- {
- T data;
-
- protected TypedAsyncResult(AsyncCallback callback, object state)
- : base(callback, state)
- {
- }
-
- public T Data
- {
- get { return data; }
- }
-
- protected void Complete(T data, bool completedSynchronously)
- {
- this.data = data;
- Complete(completedSynchronously);
- }
-
- public static T End(IAsyncResult result)
- {
- TypedAsyncResult typedResult = FileStoreAsyncResult.End>(result);
- return typedResult.Data;
- }
- }
-}
\ No newline at end of file
diff --git a/src/Microsoft.PowerShell.Workflow.ServiceCore/ServiceCore/WorkflowCore/FileInstanceStore/TypedCompletedAsyncResult.cs b/src/Microsoft.PowerShell.Workflow.ServiceCore/ServiceCore/WorkflowCore/FileInstanceStore/TypedCompletedAsyncResult.cs
deleted file mode 100644
index 92ce3cde66..0000000000
--- a/src/Microsoft.PowerShell.Workflow.ServiceCore/ServiceCore/WorkflowCore/FileInstanceStore/TypedCompletedAsyncResult.cs
+++ /dev/null
@@ -1,35 +0,0 @@
-/********************************************************************++
-Copyright (c) Microsoft Corporation. All rights reserved.
---********************************************************************/
-
-namespace Microsoft.PowerShell.Workflow
-{
- using System;
- using System.Diagnostics;
- using System.Threading;
-
- ///
- /// A strongly typed AsyncResult that completes as soon as it is instantiated.
- ///
- ///
- class TypedCompletedAsyncResult : TypedAsyncResult
- {
- public TypedCompletedAsyncResult(T data, AsyncCallback callback, object state)
- : base(callback, state)
- {
- Complete(data, true);
- }
-
- public new static T End(IAsyncResult result)
- {
- TypedCompletedAsyncResult completedResult = result as TypedCompletedAsyncResult;
-
- if (completedResult == null)
- {
- throw new ArgumentException(Resources.InvalidAsyncResult);
- }
-
- return TypedAsyncResult.End(completedResult);
- }
- }
-}
\ No newline at end of file
diff --git a/src/Microsoft.PowerShell.Workflow.ServiceCore/ServiceCore/WorkflowCore/FileInstanceStore/WorkflowAdditionalStores.cs b/src/Microsoft.PowerShell.Workflow.ServiceCore/ServiceCore/WorkflowCore/FileInstanceStore/WorkflowAdditionalStores.cs
deleted file mode 100644
index 70b065a4b6..0000000000
--- a/src/Microsoft.PowerShell.Workflow.ServiceCore/ServiceCore/WorkflowCore/FileInstanceStore/WorkflowAdditionalStores.cs
+++ /dev/null
@@ -1,2039 +0,0 @@
-/********************************************************************++
-Copyright (c) Microsoft Corporation. All rights reserved.
---********************************************************************/
-
-using System.Diagnostics;
-using System.IO.Compression;
-using System.Management.Automation.Remoting;
-
-namespace Microsoft.PowerShell.Workflow
-{
- using System;
- using System.IO;
- using System.Management.Automation;
- using System.Collections.Generic;
- using System.Collections.ObjectModel;
- using System.Runtime.Serialization;
- using System.Xml.Linq;
- using System.Runtime.DurableInstancing;
- using System.Globalization;
- using System.Management.Automation.Tracing;
- using System.Activities.DurableInstancing;
- using System.Activities.Persistence;
- using System.Reflection;
- using Microsoft.PowerShell.Commands;
- using System.Text;
-
- internal class PersistenceVersion
- {
- private readonly PowerShellTraceSource Tracer = PowerShellTraceSourceFactory.GetTraceSource();
- private bool saved = false;
- private object syncLock = new object();
-
- internal Version StoreVersion { get; set; }
- internal Version CLRVersion { get; set; }
- internal bool EnableEncryption { get; set; }
- internal bool EnableCompression { get; set; }
-
- internal PersistenceVersion(bool enableEncryption, bool enableCompression)
- {
- StoreVersion = new Version(1, 0);
- CLRVersion = Environment.Version;
- EnableEncryption = enableEncryption;
- EnableCompression = enableCompression;
- }
-
- internal void save(string versionFileName)
- {
- if (saved) return;
-
- lock (syncLock)
- {
-
- if (saved) return;
- saved = true;
-
- if (File.Exists(versionFileName))
- return;
-
- XElement versionXml = new XElement("PersistenceVersion",
- new XElement("StoreVersion", StoreVersion),
- new XElement("CLRVersion", CLRVersion),
- new XElement("EnableEncryption", EnableEncryption),
- new XElement("EnableCompression", EnableCompression));
-
- versionXml.Save(versionFileName);
- }
- }
-
- internal void load(string versionFileName)
- {
- try
- {
- if (!File.Exists(versionFileName))
- return; // use the value provided in the constructor
-
- XElement versionXml = XElement.Load(versionFileName);
-
- if (versionXml.Name.LocalName.Equals("PersistenceVersion", StringComparison.OrdinalIgnoreCase))
- {
- foreach (XElement x in versionXml.Elements())
- {
- if (x.Name.LocalName.Equals("StoreVersion", StringComparison.OrdinalIgnoreCase))
- {
- this.StoreVersion = new Version(x.Value);
- }
- else if (x.Name.LocalName.Equals("CLRVersion", StringComparison.OrdinalIgnoreCase))
- {
- this.CLRVersion = new Version(x.Value);
- }
- else if (x.Name.LocalName.Equals("EnableEncryption", StringComparison.OrdinalIgnoreCase))
- {
- this.EnableEncryption = Convert.ToBoolean(x.Value, CultureInfo.InvariantCulture);
- }
- else if (x.Name.LocalName.Equals("EnableCompression", StringComparison.OrdinalIgnoreCase))
- {
- this.EnableCompression = Convert.ToBoolean(x.Value, CultureInfo.InvariantCulture);
- }
- }
- }
- }
- catch (Exception e)
- {
- //default values will be used
- Tracer.WriteMessage(string.Format(CultureInfo.InvariantCulture, "Exception while reading or parsing the version file: {0}", versionFileName));
- Tracer.TraceException(e);
- }
- }
- }
-
-
-
- internal enum InternalStoreComponents
- {
- Streams = 0,
- Metadata = 1,
- Definition = 2,
- Timer = 3,
- JobState = 4,
- TerminatingError = 5,
- Context = 6,
- ActivityState = 7,
- }
-
- ///
- /// This class implements the functionality for storing the streams data on to the disk.
- ///
- public class PSWorkflowFileInstanceStore : PSWorkflowInstanceStore
- {
- # region private variables
-
- private readonly PowerShellTraceSource Tracer = PowerShellTraceSourceFactory.GetTraceSource();
- private static readonly Tracer etwTracer = new Tracer();
-
- private readonly string Streams = "Str";
- private readonly string Error = "Err";
- private readonly string Metadatas = "Meta";
- private readonly string Definition = "Def";
- private readonly string WorkflowState = "Stat";
-
- private readonly string Version_xml = "V.xml";
-
- private readonly string InputStream_xml = "IS.xml";
- private readonly string OutputStream_xml = "OS.xml";
- private readonly string ErrorStream_xml = "ES.xml";
- private readonly string WarningStream_xml = "WS.xml";
- private readonly string VerboseStream_xml = "VS.xml";
- private readonly string ProgressStream_xml = "PS.xml";
- private readonly string DebugStream_xml = "DS.xml";
- private readonly string InformationStream_xml = "INFS.xml";
-
- private readonly string ErrorException_xml = "EE.xml";
-
- private readonly string Input_xml = "I.xml";
- private readonly string PSWorkflowCommonParameters_xml = "UI.xml";
- private readonly string JobMetadata_xml = "JM.xml";
- private readonly string PrivateMetadata_xml = "PM.xml";
- private readonly string Timer_xml = "TI.xml";
-
- private readonly string WorkflowInstanceState_xml = "WS.xml";
-
- private readonly string WorkflowDefinition_xaml = "WD.xaml";
- private readonly string RuntimeAssembly_dll = "RA.dll";
- private readonly string RequiredAssemblies_xml = "RA.xml";
-
- private readonly string State_xml = "S.xml";
-
- private readonly string ActivityState_xml = "AS.xml";
-
- private readonly object _syncLock = new object();
-
- private bool firstTimeStoringDefinition;
-
- private PSWorkflowConfigurationProvider _configuration;
-
- private Dictionary SavedComponentLengths;
-
- private long writtenTotalBytes = 0;
-
- # endregion
-
- // For testing purpose ONLY
- internal static bool TestMode = false;
- // For testing purpose ONLY
- internal static long ObjectCounter = 0;
-
- ///
- /// Returns all Workflow guids.
- ///
- ///
- public static IEnumerable GetAllWorkflowInstanceIds()
- {
- PSWorkflowConfigurationProvider _configuration = (PSWorkflowConfigurationProvider) PSWorkflowRuntime.Instance.Configuration;
- DirectoryInfo dir = new DirectoryInfo(_configuration.InstanceStorePath);
- if (dir.Exists)
- {
- foreach (DirectoryInfo childDir in dir.GetDirectories())
- {
- Guid id;
- if (Guid.TryParse(childDir.Name, out id))
- yield return new PSWorkflowId(id);
- }
- }
- }
-
-
- ///
- /// PSWorkflowFileInstanceStore ctor
- ///
- ///
- ///
- public PSWorkflowFileInstanceStore(PSWorkflowConfigurationProvider configuration, PSWorkflowInstance instance)
- : base(instance)
- {
- if (configuration == null)
- throw new ArgumentNullException("configuration");
-
- if (TestMode)
- {
- System.Threading.Interlocked.Increment(ref ObjectCounter);
- }
-
- _configuration = configuration;
- firstTimeStoringDefinition = true;
- SavedComponentLengths = new Dictionary();
-
- bool enableCompression = true;
- _disablePersistenceLimits = true;
- if (PSSessionConfigurationData.IsServerManager)
- {
- enableCompression = false;
- _disablePersistenceLimits = false;
- }
-
- _version = new PersistenceVersion(_configuration.PersistWithEncryption, enableCompression);
- _version.load(Path.Combine(_configuration.InstanceStorePath, PSWorkflowInstance.Id.ToString(), Version_xml));
- }
-
- private void SaveVersionFile()
- {
- string storePath = Path.Combine(_configuration.InstanceStorePath, PSWorkflowInstance.Id.ToString());
- EnsureInstancePath(storePath);
-
- _version.save(Path.Combine(storePath, Version_xml));
- }
-
- private PersistenceVersion _version;
-
- ///
- /// CreateInstanceStore
- ///
- ///
- public override InstanceStore CreateInstanceStore()
- {
- return new FileInstanceStore(this);
- }
-
- ///
- /// CreatePersistenceIOParticipant
- ///
- ///
- public override PersistenceIOParticipant CreatePersistenceIOParticipant()
- {
- return null;
- }
-
- # region Serialization
-
- ///
- /// To be called from test code only.
- ///
- ///
- internal void CallDoSave(IEnumerable