No Description
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

PlasticConnectionMonitor.cs 6.6KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234
  1. using System;
  2. using System.Threading;
  3. using UnityEditor;
  4. using Codice.Client.Common.EventTracking;
  5. using Codice.Client.Common.Connection;
  6. using Codice.Client.Common.Threading;
  7. using Codice.CM.Common;
  8. using Codice.LogWrapper;
  9. using PlasticPipe;
  10. using Unity.PlasticSCM.Editor.UI;
  11. namespace Unity.PlasticSCM.Editor
  12. {
  13. internal class PlasticConnectionMonitor :
  14. HandleCredsAliasAndServerCert.IHostUnreachableExceptionListener
  15. {
  16. internal bool IsTryingReconnection { get { return mIsTryingReconnection; } }
  17. internal bool IsConnected { get { return PlasticPlugin.IsUnitTesting || mIsConnected; } }
  18. internal void CheckConnection()
  19. {
  20. mIsTryingReconnection = true;
  21. mResetEvent.Set();
  22. }
  23. internal void SetAsConnected()
  24. {
  25. mIsConnected = true;
  26. }
  27. internal void Stop()
  28. {
  29. if (!mIsMonitoringServerConnection)
  30. return;
  31. mLog.Debug("Stop");
  32. mIsMonitoringServerConnection = false;
  33. mResetEvent.Set();
  34. }
  35. internal void SetRepositorySpecForEventTracking(RepositorySpec repSpec)
  36. {
  37. mRepSpecForEventTracking = repSpec;
  38. }
  39. internal void OnConnectionError(Exception ex, string server)
  40. {
  41. lock (mOnConnectionErrorLock)
  42. {
  43. LogConnectionError(ex, mIsConnected);
  44. if (!mIsConnected)
  45. return;
  46. mIsConnected = false;
  47. }
  48. HandleConnectionLost(
  49. mRepSpecForEventTracking,
  50. () => StartMonitoring(server));
  51. }
  52. void HandleCredsAliasAndServerCert.IHostUnreachableExceptionListener.OnHostUnreachableException(
  53. Exception ex,
  54. PlasticServer plasticServer)
  55. {
  56. OnConnectionError(ex, plasticServer.OriginalUrl);
  57. }
  58. void StartMonitoring(string server)
  59. {
  60. mLog.Debug("StartMonitoring");
  61. mIsMonitoringServerConnection = true;
  62. Thread thread = new Thread(MonitorServerConnection);
  63. thread.IsBackground = true;
  64. thread.Name = "Plastic SCM Connection Monitor thread";
  65. thread.Start(server);
  66. }
  67. void MonitorServerConnection(object obj)
  68. {
  69. string server = (string)obj;
  70. while (true)
  71. {
  72. if (!mIsMonitoringServerConnection)
  73. break;
  74. try
  75. {
  76. mResetEvent.Reset();
  77. if (HasConnectionToServer(server))
  78. {
  79. mIsConnected = true;
  80. HandleConnectionRestored(mRepSpecForEventTracking);
  81. break;
  82. }
  83. RepaintPlasticWindowIfOpened();
  84. mResetEvent.WaitOne(CONNECTION_POLL_TIME_MS);
  85. }
  86. catch (Exception ex)
  87. {
  88. mLog.Error("Error checking network connectivity", ex);
  89. mLog.DebugFormat("Stacktrace: {0}", ex.StackTrace);
  90. }
  91. finally
  92. {
  93. mIsTryingReconnection = false;
  94. }
  95. }
  96. }
  97. static void HandleConnectionLost(
  98. RepositorySpec repSpecForEventTracking,
  99. Action startMonitoringAction)
  100. {
  101. TrackConnectionLostEvent(repSpecForEventTracking);
  102. EditorDispatcher.Dispatch(() =>
  103. {
  104. PlasticPlugin.Disable();
  105. startMonitoringAction();
  106. PlasticWindow window = GetPlasticWindowIfOpened();
  107. if (window != null)
  108. window.Repaint();
  109. });
  110. }
  111. static void HandleConnectionRestored(
  112. RepositorySpec repSpecForEventTracking)
  113. {
  114. TrackConnectionRestoredEvent(repSpecForEventTracking);
  115. EditorDispatcher.Dispatch(() =>
  116. {
  117. PlasticPlugin.Enable();
  118. PlasticWindow window = GetPlasticWindowIfOpened();
  119. if (window != null)
  120. window.RefreshWorkspaceUI();
  121. });
  122. }
  123. static void RepaintPlasticWindowIfOpened()
  124. {
  125. EditorDispatcher.Dispatch(() =>
  126. {
  127. PlasticWindow window = GetPlasticWindowIfOpened();
  128. if (window != null)
  129. window.Repaint();
  130. });
  131. }
  132. static void LogConnectionError(Exception ex, bool isConnected)
  133. {
  134. mLog.WarnFormat(isConnected ?
  135. "A network exception will cause the plugin to go offline" :
  136. "A network exception happened while the plugin was offline!");
  137. ExceptionsHandler.LogException("PlasticConnectionMonitor", ex);
  138. }
  139. static void TrackConnectionLostEvent(RepositorySpec repSpec)
  140. {
  141. if (repSpec == null)
  142. return;
  143. TrackFeatureUseEvent.For(
  144. repSpec,
  145. TrackFeatureUseEvent.Features.UnityPackage.DisableAutomatically);
  146. }
  147. static void TrackConnectionRestoredEvent(RepositorySpec repSpec)
  148. {
  149. if (repSpec == null)
  150. return;
  151. TrackFeatureUseEvent.For(
  152. repSpec,
  153. TrackFeatureUseEvent.Features.UnityPackage.EnableAutomatically);
  154. }
  155. static PlasticWindow GetPlasticWindowIfOpened()
  156. {
  157. if (!EditorWindow.HasOpenInstances<PlasticWindow>())
  158. return null;
  159. return EditorWindow.GetWindow<PlasticWindow>(null, false);
  160. }
  161. static bool HasConnectionToServer(string server)
  162. {
  163. try
  164. {
  165. mLog.DebugFormat("Checking connection to {0}...", server);
  166. return PlasticGui.Plastic.API.CheckServerConnection(server);
  167. }
  168. catch (Exception ex)
  169. {
  170. mLog.DebugFormat("Checking connection to {0} failed: {1}",
  171. server,
  172. ex.Message);
  173. return false;
  174. }
  175. }
  176. volatile bool mIsMonitoringServerConnection;
  177. volatile bool mIsTryingReconnection;
  178. volatile bool mIsConnected = true;
  179. RepositorySpec mRepSpecForEventTracking;
  180. readonly object mOnConnectionErrorLock = new object();
  181. readonly ManualResetEvent mResetEvent = new ManualResetEvent(false);
  182. const int CONNECTION_POLL_TIME_MS = 30000;
  183. static readonly ILog mLog = PlasticApp.GetLogger("PlasticConnectionMonitor");
  184. }
  185. }