Ping the connected host regularly and check other hosts at lower freq.

* This lets us detect when a remote server has been disconnected and
  needs to be restarted, as well as alerting the user if this happens in
  the middle of a replay session.
* Pinging other hosts means the context switcher is reasonably up to
  date if one of them comes up.
This commit is contained in:
baldurk
2016-08-23 15:21:52 +02:00
parent 0ddfd3d65b
commit f8bbedeb8b
5 changed files with 148 additions and 11 deletions
+4
View File
@@ -480,6 +480,8 @@ struct IRemoteServer
virtual void ShutdownServerAndConnection() = 0;
virtual bool Ping() = 0;
virtual bool LocalProxies(rdctype::array<rdctype::str> *out) = 0;
virtual bool RemoteSupportedReplays(rdctype::array<rdctype::str> *out) = 0;
@@ -517,6 +519,8 @@ extern "C" RENDERDOC_API void RENDERDOC_CC RemoteServer_ShutdownConnection(Remot
extern "C" RENDERDOC_API void RENDERDOC_CC
RemoteServer_ShutdownServerAndConnection(RemoteServer *remote);
extern "C" RENDERDOC_API bool32 RENDERDOC_CC RemoteServer_Ping(RemoteServer *remote);
extern "C" RENDERDOC_API bool32 RENDERDOC_CC
RemoteServer_LocalProxies(RemoteServer *remote, rdctype::array<rdctype::str> *out);
extern "C" RENDERDOC_API bool32 RENDERDOC_CC
+27
View File
@@ -75,6 +75,7 @@ enum RemoteServerPacket
eRemoteServer_VersionMismatch,
eRemoteServer_Busy,
eRemoteServer_Ping,
eRemoteServer_RemoteDriverList,
eRemoteServer_TakeOwnershipCapture,
eRemoteServer_CopyCaptureToRemote,
@@ -245,6 +246,10 @@ static void ActiveRemoteClientThread(void *data)
SAFE_DELETE(recvser);
continue;
}
else if(type == eRemoteServer_Ping)
{
sendType = eRemoteServer_Ping;
}
else if(type == eRemoteServer_RemoteDriverList)
{
map<RDCDriver, string> drivers = RenderDoc::Inst().GetRemoteDrivers();
@@ -721,6 +726,23 @@ public:
delete this;
}
bool Connected() { return m_Socket != NULL && m_Socket->Connected(); }
bool Ping()
{
if(!Connected())
return false;
Serialiser sendData("", Serialiser::WRITING, false);
Send(eRemoteServer_Ping, sendData);
RemoteServerPacket type = eRemoteServer_Noop;
Serialiser *ser = NULL;
Get(type, &ser);
SAFE_DELETE(ser);
return type == eRemoteServer_Ping;
}
bool LocalProxies(rdctype::array<rdctype::str> *out)
{
if(out == NULL)
@@ -1078,6 +1100,11 @@ extern "C" RENDERDOC_API void RENDERDOC_CC RemoteServer_ShutdownServerAndConnect
remote->ShutdownServerAndConnection();
}
extern "C" RENDERDOC_API bool32 RENDERDOC_CC RemoteServer_Ping(RemoteServer *remote)
{
return remote->Ping();
}
extern "C" RENDERDOC_API bool32 RENDERDOC_CC
RemoteServer_LocalProxies(RemoteServer *remote, rdctype::array<rdctype::str> *out)
{
+25
View File
@@ -70,6 +70,8 @@ namespace renderdocui.Code
private List<InvokeHandle> m_renderQueue;
private InvokeHandle m_current = null;
private bool m_CopyInProgress = false;
////////////////////////////////////////////
// Interface
@@ -217,8 +219,13 @@ namespace renderdocui.Code
{
Helpers.NewThread(new ThreadStart(() =>
{
// prevent pings while copying off-thread
m_CopyInProgress = true;
remotepath = m_Remote.CopyCaptureToRemote(localpath, ref progress);
m_CopyInProgress = false;
copied = true;
})).Start();
}
@@ -271,8 +278,13 @@ namespace renderdocui.Code
{
Helpers.NewThread(new ThreadStart(() =>
{
// prevent pings while copying off-thread
m_CopyInProgress = true;
m_Remote.CopyCaptureFromRemote(remotepath, localpath, ref progress);
m_CopyInProgress = false;
copied = true;
})).Start();
}
@@ -328,6 +340,19 @@ namespace renderdocui.Code
m_Remote = null;
}
public void PingRemote()
{
if(m_CopyInProgress)
return;
// must only happen on render thread if running
if ((!Running || m_Thread == Thread.CurrentThread) && m_Remote != null)
{
if (!m_Remote.Ping())
m_RemoteHost.ServerRunning = false;
}
}
public ReplayCreateException InitException = null;
public void CloseThreadSync()
+8
View File
@@ -892,6 +892,9 @@ namespace renderdoc
[DllImport("renderdoc.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Cdecl)]
private static extern void RemoteServer_ShutdownServerAndConnection(IntPtr real);
[DllImport("renderdoc.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Cdecl)]
private static extern bool RemoteServer_Ping(IntPtr real);
[DllImport("renderdoc.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Cdecl)]
private static extern bool RemoteServer_LocalProxies(IntPtr real, IntPtr outlist);
[DllImport("renderdoc.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Cdecl)]
@@ -986,6 +989,11 @@ namespace renderdoc
return ret;
}
public bool Ping()
{
return RemoteServer_Ping(m_Real);
}
public string[] LocalProxies()
{
IntPtr mem = CustomMarshal.Alloc(typeof(templated_array));
+84 -11
View File
@@ -167,6 +167,9 @@ namespace renderdocui.Windows
m_Core.AddLogViewer(this);
m_Core.AddLogProgressListener(this);
m_MessageTick = new System.Threading.Timer(MessageCheck, this as object, 500, 500);
m_RemoteProbe = new System.Threading.Timer(RemoteProbe, this as object, 2500, 2500);
}
private void MainWindow_Load(object sender, EventArgs e)
@@ -268,13 +271,38 @@ namespace renderdocui.Windows
statusIcon.Image = null;
statusProgress.Visible = false;
m_MessageTick.Dispose();
m_MessageTick = null;
resolveSymbolsToolStripMenuItem.Enabled = false;
resolveSymbolsToolStripMenuItem.Text = "Resolve Symbols";
SetTitle();
// if the remote sever disconnected during log replay, resort back to a 'disconnected' state
if (m_Core.Renderer.Remote != null && !m_Core.Renderer.Remote.ServerRunning)
{
statusText.Text = "Remote server disconnected. To attempt to reconnect please select it again.";
contextChooser.Text = "Replay Context: Local";
m_Core.Renderer.DisconnectFromRemoteServer();
}
}
private static void RemoteProbe(object m)
{
if (!(m is MainWindow)) return;
var me = (MainWindow)m;
// perform a probe of known remote hosts to see if they're running or not
if (!me.m_Core.LogLoading && !me.m_Core.LogLoaded)
{
foreach (var host in me.m_Core.Config.RemoteHosts)
{
// don't mess with a host we're connected to - this is handled anyway
if (host.Connected)
continue;
host.CheckStatus();
}
}
}
private static void MessageCheck(object m)
@@ -289,8 +317,33 @@ namespace renderdocui.Windows
{
DebugMessage[] msgs = r.GetDebugMessages();
bool disconnected = false;
if(me.m_Core.Renderer.Remote != null)
{
bool prev = me.m_Core.Renderer.Remote.ServerRunning;
me.m_Core.Renderer.PingRemote();
if(prev != me.m_Core.Renderer.Remote.ServerRunning)
disconnected = true;
}
me.BeginInvoke(new Action(() =>
{
// if we just got disconnected while replaying a log, alert the user.
if (disconnected)
{
MessageBox.Show("Remote server disconnected during replaying of this capture.\n" +
"The replay will now be non-functional. To restore you will have to close the capture, allow\n" +
"RenderDoc to reconnect and load the capture again",
"Remote server disconnected",
MessageBoxButtons.OK, MessageBoxIcon.Error);
}
if (me.m_Core.Renderer.Remote != null && !me.m_Core.Renderer.Remote.ServerRunning)
me.contextChooser.Image = global::renderdocui.Properties.Resources.cross;
if (msgs.Length > 0)
{
me.m_Core.AddMessages(msgs);
@@ -310,12 +363,27 @@ namespace renderdocui.Windows
}));
});
}
else if(!me.m_Core.LogLoaded && !me.m_Core.LogLoading)
{
if (me.m_Core.Renderer.Remote != null)
me.m_Core.Renderer.PingRemote();
if (me == null) return;
if (me.m_MessageTick != null) me.m_MessageTick.Change(500, System.Threading.Timeout.Infinite);
me.BeginInvoke(new Action(() =>
{
if (me.m_Core.Renderer.Remote != null && !me.m_Core.Renderer.Remote.ServerRunning)
{
me.contextChooser.Image = global::renderdocui.Properties.Resources.cross;
me.contextChooser.Text = "Replay Context: Local";
me.statusText.Text = "Remote server disconnected. To attempt to reconnect please select it again.";
me.m_Core.Renderer.DisconnectFromRemoteServer();
}
}));
}
}
private System.Threading.Timer m_MessageTick = null;
private System.Threading.Timer m_RemoteProbe = null;
private bool m_MessageAlternate = false;
private bool LogHasErrors
@@ -354,8 +422,6 @@ namespace renderdocui.Windows
LogHasErrors = (m_Core.DebugMessages.Count > 0);
m_MessageTick = new System.Threading.Timer(MessageCheck, this as object, 500, System.Threading.Timeout.Infinite);
statusProgress.Visible = false;
m_Core.Renderer.BeginInvoke((ReplayRenderer r) => {
@@ -1011,12 +1077,19 @@ namespace renderdocui.Windows
ToolStripItem item = new ToolStripMenuItem();
item.Image = host.ServerRunning
item.Image = host.ServerRunning && !host.VersionMismatch
? global::renderdocui.Properties.Resources.tick
: global::renderdocui.Properties.Resources.cross;
item.Text = host.ServerRunning
? String.Format("{0} (Online)", host.Hostname)
: String.Format("{0} (Offline)", host.Hostname);
if (host.Connected)
item.Text = String.Format("{0} (Connected)", host.Hostname);
else if (host.ServerRunning && host.VersionMismatch)
item.Text = String.Format("{0} (Bad Version)", host.Hostname);
else if (host.ServerRunning && host.Busy)
item.Text = String.Format("{0} (Busy)", host.Hostname);
else if (host.ServerRunning)
item.Text = String.Format("{0} (Online)", host.Hostname);
else
item.Text = String.Format("{0} (Offline)", host.Hostname);
item.Click += new EventHandler(switchContext);
item.Tag = host;