123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234 |
- using System;
- using System.Threading;
-
- using UnityEditor;
-
- using Codice.Client.Common.EventTracking;
- using Codice.Client.Common.Connection;
- using Codice.Client.Common.Threading;
- using Codice.CM.Common;
- using Codice.LogWrapper;
- using PlasticPipe;
- using Unity.PlasticSCM.Editor.UI;
-
- namespace Unity.PlasticSCM.Editor
- {
- internal class PlasticConnectionMonitor :
- HandleCredsAliasAndServerCert.IHostUnreachableExceptionListener
- {
- internal bool IsTryingReconnection { get { return mIsTryingReconnection; } }
- internal bool IsConnected { get { return PlasticPlugin.IsUnitTesting || mIsConnected; } }
-
- internal void CheckConnection()
- {
- mIsTryingReconnection = true;
- mResetEvent.Set();
- }
-
- internal void SetAsConnected()
- {
- mIsConnected = true;
- }
-
- internal void Stop()
- {
- if (!mIsMonitoringServerConnection)
- return;
-
- mLog.Debug("Stop");
-
- mIsMonitoringServerConnection = false;
- mResetEvent.Set();
- }
-
- internal void SetRepositorySpecForEventTracking(RepositorySpec repSpec)
- {
- mRepSpecForEventTracking = repSpec;
- }
-
- internal void OnConnectionError(Exception ex, string server)
- {
- lock (mOnConnectionErrorLock)
- {
- LogConnectionError(ex, mIsConnected);
-
- if (!mIsConnected)
- return;
-
- mIsConnected = false;
- }
-
- HandleConnectionLost(
- mRepSpecForEventTracking,
- () => StartMonitoring(server));
- }
-
- void HandleCredsAliasAndServerCert.IHostUnreachableExceptionListener.OnHostUnreachableException(
- Exception ex,
- PlasticServer plasticServer)
- {
- OnConnectionError(ex, plasticServer.OriginalUrl);
- }
-
- void StartMonitoring(string server)
- {
- mLog.Debug("StartMonitoring");
-
- mIsMonitoringServerConnection = true;
-
- Thread thread = new Thread(MonitorServerConnection);
- thread.IsBackground = true;
- thread.Name = "Plastic SCM Connection Monitor thread";
- thread.Start(server);
- }
-
- void MonitorServerConnection(object obj)
- {
- string server = (string)obj;
-
- while (true)
- {
- if (!mIsMonitoringServerConnection)
- break;
-
- try
- {
- mResetEvent.Reset();
-
- if (HasConnectionToServer(server))
- {
- mIsConnected = true;
- HandleConnectionRestored(mRepSpecForEventTracking);
- break;
- }
-
- RepaintPlasticWindowIfOpened();
-
- mResetEvent.WaitOne(CONNECTION_POLL_TIME_MS);
- }
- catch (Exception ex)
- {
- mLog.Error("Error checking network connectivity", ex);
- mLog.DebugFormat("Stacktrace: {0}", ex.StackTrace);
- }
- finally
- {
- mIsTryingReconnection = false;
- }
- }
- }
-
- static void HandleConnectionLost(
- RepositorySpec repSpecForEventTracking,
- Action startMonitoringAction)
- {
- TrackConnectionLostEvent(repSpecForEventTracking);
-
- EditorDispatcher.Dispatch(() =>
- {
- PlasticPlugin.Disable();
-
- startMonitoringAction();
-
- PlasticWindow window = GetPlasticWindowIfOpened();
-
- if (window != null)
- window.Repaint();
- });
- }
-
- static void HandleConnectionRestored(
- RepositorySpec repSpecForEventTracking)
- {
- TrackConnectionRestoredEvent(repSpecForEventTracking);
-
- EditorDispatcher.Dispatch(() =>
- {
- PlasticPlugin.Enable();
-
- PlasticWindow window = GetPlasticWindowIfOpened();
-
- if (window != null)
- window.RefreshWorkspaceUI();
- });
- }
-
- static void RepaintPlasticWindowIfOpened()
- {
- EditorDispatcher.Dispatch(() =>
- {
- PlasticWindow window = GetPlasticWindowIfOpened();
-
- if (window != null)
- window.Repaint();
- });
- }
-
- static void LogConnectionError(Exception ex, bool isConnected)
- {
- mLog.WarnFormat(isConnected ?
- "A network exception will cause the plugin to go offline" :
- "A network exception happened while the plugin was offline!");
-
- ExceptionsHandler.LogException("PlasticConnectionMonitor", ex);
- }
-
- static void TrackConnectionLostEvent(RepositorySpec repSpec)
- {
- if (repSpec == null)
- return;
-
- TrackFeatureUseEvent.For(
- repSpec,
- TrackFeatureUseEvent.Features.UnityPackage.DisableAutomatically);
- }
-
- static void TrackConnectionRestoredEvent(RepositorySpec repSpec)
- {
- if (repSpec == null)
- return;
-
- TrackFeatureUseEvent.For(
- repSpec,
- TrackFeatureUseEvent.Features.UnityPackage.EnableAutomatically);
- }
-
- static PlasticWindow GetPlasticWindowIfOpened()
- {
- if (!EditorWindow.HasOpenInstances<PlasticWindow>())
- return null;
-
- return EditorWindow.GetWindow<PlasticWindow>(null, false);
- }
-
- static bool HasConnectionToServer(string server)
- {
- try
- {
- mLog.DebugFormat("Checking connection to {0}...", server);
-
- return PlasticGui.Plastic.API.CheckServerConnection(server);
- }
- catch (Exception ex)
- {
- mLog.DebugFormat("Checking connection to {0} failed: {1}",
- server,
- ex.Message);
- return false;
- }
- }
-
- volatile bool mIsMonitoringServerConnection;
- volatile bool mIsTryingReconnection;
- volatile bool mIsConnected = true;
-
- RepositorySpec mRepSpecForEventTracking;
-
- readonly object mOnConnectionErrorLock = new object();
- readonly ManualResetEvent mResetEvent = new ManualResetEvent(false);
-
- const int CONNECTION_POLL_TIME_MS = 30000;
-
- static readonly ILog mLog = PlasticApp.GetLogger("PlasticConnectionMonitor");
- }
- }
|