212 lines
5.9 KiB
C#
212 lines
5.9 KiB
C#
|
using System;
|
|||
|
using System.Threading;
|
|||
|
|
|||
|
using UnityEditor;
|
|||
|
|
|||
|
using Codice.Client.BaseCommands.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()
|
|||
|
{
|
|||
|
mIsMonitoringServerConnection = false;
|
|||
|
mResetEvent.Set();
|
|||
|
}
|
|||
|
|
|||
|
internal void SetRepositorySpecForEventTracking(RepositorySpec repSpec)
|
|||
|
{
|
|||
|
mRepSpecForEventTracking = repSpec;
|
|||
|
}
|
|||
|
|
|||
|
internal void OnConnectionError(Exception ex, string server)
|
|||
|
{
|
|||
|
if (!mIsConnected)
|
|||
|
{
|
|||
|
mLog.WarnFormat("A network exception happened while the plugin was offline!");
|
|||
|
ExceptionsHandler.LogException("PlasticConnectionMonitor", ex);
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
mLog.Debug("A network exception will cause the Plugin to go offline");
|
|||
|
ExceptionsHandler.LogException("PlasticConnectionMonitor", ex);
|
|||
|
|
|||
|
OnConnectionLost(server);
|
|||
|
}
|
|||
|
|
|||
|
void HandleCredsAliasAndServerCert.IHostUnreachableExceptionListener.OnHostUnreachableException(
|
|||
|
Exception ex,
|
|||
|
PlasticServer plasticServer)
|
|||
|
{
|
|||
|
OnConnectionError(ex, plasticServer.OriginalUrl);
|
|||
|
}
|
|||
|
|
|||
|
void StartMonitoring(string server)
|
|||
|
{
|
|||
|
mIsMonitoringServerConnection = true;
|
|||
|
|
|||
|
Thread thread = new Thread(MonitorServerConnection);
|
|||
|
thread.IsBackground = true;
|
|||
|
thread.Start(server);
|
|||
|
}
|
|||
|
|
|||
|
void MonitorServerConnection(object obj)
|
|||
|
{
|
|||
|
string server = (string)obj;
|
|||
|
|
|||
|
while (true)
|
|||
|
{
|
|||
|
if (!mIsMonitoringServerConnection)
|
|||
|
break;
|
|||
|
|
|||
|
try
|
|||
|
{
|
|||
|
bool isConnected;
|
|||
|
|
|||
|
mResetEvent.Reset();
|
|||
|
|
|||
|
isConnected = HasConnectionToServer(server);
|
|||
|
|
|||
|
mIsTryingReconnection = false;
|
|||
|
|
|||
|
if (isConnected)
|
|||
|
{
|
|||
|
OnConnectionRestored();
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
EditorDispatcher.Dispatch(() =>
|
|||
|
{
|
|||
|
PlasticWindow window = GetPlasticWindowIfOpened();
|
|||
|
|
|||
|
if (window != null)
|
|||
|
window.Repaint();
|
|||
|
});
|
|||
|
|
|||
|
mResetEvent.WaitOne(CONNECTION_POLL_TIME_MS);
|
|||
|
}
|
|||
|
catch (Exception ex)
|
|||
|
{
|
|||
|
mLog.Error("Error checking network connectivity", ex);
|
|||
|
mLog.DebugFormat("Stacktrace: {0}", ex.StackTrace);
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
void OnConnectionLost(string server)
|
|||
|
{
|
|||
|
TrackConnectionLostEvent(mRepSpecForEventTracking);
|
|||
|
|
|||
|
mIsConnected = false;
|
|||
|
|
|||
|
EditorDispatcher.Dispatch(() =>
|
|||
|
{
|
|||
|
PlasticPlugin.Disable();
|
|||
|
|
|||
|
StartMonitoring(server);
|
|||
|
|
|||
|
PlasticWindow window = GetPlasticWindowIfOpened();
|
|||
|
|
|||
|
if (window != null)
|
|||
|
window.Repaint();
|
|||
|
});
|
|||
|
}
|
|||
|
|
|||
|
void OnConnectionRestored()
|
|||
|
{
|
|||
|
TrackConnectionRestoredEvent(mRepSpecForEventTracking);
|
|||
|
|
|||
|
mIsConnected = true;
|
|||
|
|
|||
|
EditorDispatcher.Dispatch(() =>
|
|||
|
{
|
|||
|
PlasticPlugin.Enable();
|
|||
|
|
|||
|
PlasticWindow window = GetPlasticWindowIfOpened();
|
|||
|
|
|||
|
if (window != null)
|
|||
|
window.RefreshWorkspaceUI();
|
|||
|
});
|
|||
|
}
|
|||
|
|
|||
|
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;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
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);
|
|||
|
}
|
|||
|
|
|||
|
RepositorySpec mRepSpecForEventTracking;
|
|||
|
|
|||
|
volatile bool mIsMonitoringServerConnection;
|
|||
|
volatile bool mIsTryingReconnection;
|
|||
|
volatile bool mIsConnected = true;
|
|||
|
|
|||
|
ManualResetEvent mResetEvent = new ManualResetEvent(false);
|
|||
|
|
|||
|
const int CONNECTION_POLL_TIME_MS = 30000;
|
|||
|
|
|||
|
static readonly ILog mLog = LogManager.GetLogger("PlasticConnectionMonitor");
|
|||
|
}
|
|||
|
}
|