Merge pull request #1697 from kc284/CA-257927

CA-257927: Fixed scalability issue where XenCenter froze momentarily when disconnecting from a host with a big number of alerts
This commit is contained in:
Mihaela Stoica 2017-07-26 08:43:22 +01:00 committed by GitHub
commit 2a4335231e
12 changed files with 256 additions and 122 deletions

View File

@ -131,19 +131,37 @@ namespace XenAdmin.Controls.MainWindowControls
public void XenConnectionCollectionChanged(CollectionChangeEventArgs e)
{
IXenConnection connection = (IXenConnection)e.Element;
if (connection == null)
return;
IXenConnection connection = e.Element as IXenConnection;
if (e.Action == CollectionChangeAction.Add)
{
if (connection == null)
return;
connection.BeforeMajorChange += Connection_BeforeMajorChange;
connection.AfterMajorChange += Connection_AfterMajorChange;
}
else if (e.Action == CollectionChangeAction.Remove)
{
connection.BeforeMajorChange -= Connection_BeforeMajorChange;
connection.AfterMajorChange -= Connection_AfterMajorChange;
var range = new List<IXenConnection>();
if (connection != null)
{
range.Add(connection);
}
else
{
var r = e.Element as List<IXenConnection>;
if (r != null)
range = r;
else
return;
}
foreach (var con in range)
{
con.BeforeMajorChange -= Connection_BeforeMajorChange;
con.AfterMajorChange -= Connection_AfterMajorChange;
}
}
}

View File

@ -196,7 +196,7 @@ namespace XenAdmin.Dialogs.WarningDialogs
{
Program.BeginInvoke(this, () =>
{
ActionBase action = (ActionBase)e.Element;
ActionBase action = e.Element as ActionBase;
switch (e.Action)
{
case CollectionChangeAction.Add:
@ -211,7 +211,16 @@ namespace XenAdmin.Dialogs.WarningDialogs
}
break;
case CollectionChangeAction.Remove:
RemoveActionRow(action);
if (action != null)
{
RemoveActionRow(action);
}
else
{
var range = e.Element as List<ActionBase>;
if (range != null)
BuildList();
}
break;
case CollectionChangeAction.Refresh:
BuildList();

View File

@ -393,14 +393,15 @@ namespace XenAdmin
Program.BeginInvoke(Program.MainWindow, () =>
{
ActionBase action = (ActionBase)e.Element;
if (action == null)
return;
ActionBase action = e.Element as ActionBase;
switch (e.Action)
{
case CollectionChangeAction.Add:
{
if (action == null)
return;
var meddlingAction = action as MeddlingAction;
if (meddlingAction == null)
{
@ -419,9 +420,28 @@ namespace XenAdmin
}
case CollectionChangeAction.Remove:
{
action.Changed -= actionChanged;
action.Completed -= actionCompleted;
if (action != null)
{
action.Changed -= actionChanged;
action.Completed -= actionCompleted;
}
else
{
var range = e.Element as List<ActionBase>;
if (range != null)
{
foreach (var a in range)
{
a.Changed -= actionChanged;
a.Completed -= actionCompleted;
}
}
else
{
return;
}
}
int errors = ConnectionsManager.History.Count(a => a.IsCompleted && !a.Succeeded);
navigationPane.UpdateNotificationsButton(NotificationsSubMode.Events, errors);
@ -752,14 +772,15 @@ namespace XenAdmin
{
try
{
IXenConnection connection = (IXenConnection)e.Element;
if (connection == null)
return;
IXenConnection connection = e.Element as IXenConnection;
navigationPane.XenConnectionCollectionChanged(e);
if (e.Action == CollectionChangeAction.Add)
{
if (connection == null)
return;
connection.ClearingCache += connection_ClearingCache;
connection.ConnectionResult += Connection_ConnectionResult;
connection.ConnectionLost += Connection_ConnectionLost;
@ -779,38 +800,54 @@ namespace XenAdmin
}
else if (e.Action == CollectionChangeAction.Remove)
{
connection.ClearingCache -= connection_ClearingCache;
connection.ConnectionResult -= Connection_ConnectionResult;
connection.ConnectionLost -= Connection_ConnectionLost;
connection.ConnectionClosed -= Connection_ConnectionClosed;
connection.ConnectionReconnecting -= connection_ConnectionReconnecting;
connection.XenObjectsUpdated -= Connection_XenObjectsUpdated;
connection.Cache.DeregisterCollectionChanged<XenAPI.Message>(MessageCollectionChangedWithInvoke);
connection.Cache.DeregisterCollectionChanged<Pool>(PoolCollectionChangedWithInvoke);
connection.Cache.DeregisterCollectionChanged<Host>(HostCollectionChangedWithInvoke);
connection.Cache.DeregisterCollectionChanged<VM>(VMCollectionChangedWithInvoke);
connection.Cache.DeregisterCollectionChanged<SR>(SRCollectionChangedWithInvoke);
connection.Cache.DeregisterCollectionChanged<Folder>(FolderCollectionChangedWithInvoke);
connection.Cache.DeregisterCollectionChanged<Task>(TaskCollectionChangedWithInvoke);
connection.CachePopulated -= connection_CachePopulated;
foreach (VM vm in connection.Cache.VMs)
var range = new List<IXenConnection>();
if (connection != null)
{
ConsolePanel.closeVNCForSource(vm);
range.Add(connection);
}
else
{
var r = e.Element as List<IXenConnection>;
if (r != null)
range = r;
else
return;
}
foreach (Host host in connection.Cache.Hosts)
foreach (var con in range)
{
ConsolePanel.closeVNCForSource(host.ControlDomainZero);
con.ClearingCache -= connection_ClearingCache;
con.ConnectionResult -= Connection_ConnectionResult;
con.ConnectionLost -= Connection_ConnectionLost;
con.ConnectionClosed -= Connection_ConnectionClosed;
con.ConnectionReconnecting -= connection_ConnectionReconnecting;
con.XenObjectsUpdated -= Connection_XenObjectsUpdated;
con.Cache.DeregisterCollectionChanged<XenAPI.Message>(MessageCollectionChangedWithInvoke);
con.Cache.DeregisterCollectionChanged<Pool>(PoolCollectionChangedWithInvoke);
con.Cache.DeregisterCollectionChanged<Host>(HostCollectionChangedWithInvoke);
con.Cache.DeregisterCollectionChanged<VM>(VMCollectionChangedWithInvoke);
con.Cache.DeregisterCollectionChanged<SR>(SRCollectionChangedWithInvoke);
con.Cache.DeregisterCollectionChanged<Folder>(FolderCollectionChangedWithInvoke);
foreach (VM vm in host.OtherControlDomains)
CvmConsolePanel.closeVNCForSource(vm);
con.Cache.DeregisterCollectionChanged<Task>(TaskCollectionChangedWithInvoke);
con.CachePopulated -= connection_CachePopulated;
foreach (VM vm in con.Cache.VMs)
{
ConsolePanel.closeVNCForSource(vm);
}
foreach (Host host in con.Cache.Hosts)
{
ConsolePanel.closeVNCForSource(host.ControlDomainZero);
foreach (VM vm in host.OtherControlDomains)
CvmConsolePanel.closeVNCForSource(vm);
}
con.EndConnect();
}
connection.EndConnect();
RequestRefreshTreeView();
//CA-41228 refresh submenu items when there are no connections
SelectionManager.RefreshSelection();

View File

@ -40,8 +40,6 @@ using System.Windows.Forms;
using XenAdmin.Controls;
using XenAdmin.Core;
using XenAdmin.Dialogs;
using XenAdmin.Network;
using XenAPI;
using XenAdmin.Alerts;
using XenAdmin.Help;
using System.Threading;
@ -411,7 +409,6 @@ namespace XenAdmin.TabPages
}
}
#endregion
private DataGridViewRow FindAlertRow(ToolStripMenuItem toolStripMenuItem)
{
@ -425,6 +422,8 @@ namespace XenAdmin.TabPages
select row).FirstOrDefault();
}
#endregion
private void ToolStripMenuItemHelp_Click(object sender, EventArgs e)
{
// We should only be here if one item is selected, we dont do multi-help
@ -585,24 +584,27 @@ namespace XenAdmin.TabPages
private void AlertsCollectionChanged(object sender, CollectionChangeEventArgs e)
{
Program.AssertOnEventThread();
if (e.Element == null)
{
// We take the null element to mean there has been a batch remove
Rebuild();
return;
}
Alert a = e.Element as Alert;
switch (e.Action)
{
case CollectionChangeAction.Add:
Rebuild(); // rebuild entire alert list to ensure filtering and sorting
break;
case CollectionChangeAction.Remove:
RemoveAlertRow(a);
var a = e.Element as Alert;
if (a != null)
RemoveAlertRow(a);
else
{
var range = e.Element as List<Alert>;
if (range != null)
Rebuild();
}
break;
}
}
private void UpdateActionEnablement()
{
toolStripButtonExportAll.Enabled = Alert.NonDismissingAlertCount > 0;

View File

@ -13,7 +13,7 @@ namespace XenAdmin.TabPages
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
ConnectionsManager.XenConnections.CollectionChanged -= History_CollectionChanged;
ConnectionsManager.History.CollectionChanged -= History_CollectionChanged;
XenAdmin.Actions.ActionBase.NewAction -= Action_NewAction;
if (disposing && (components != null))

View File

@ -93,7 +93,7 @@ namespace XenAdmin.TabPages
{
Program.BeginInvoke(this, () =>
{
ActionBase action = (ActionBase)e.Element;
ActionBase action = e.Element as ActionBase;
switch (e.Action)
{
case CollectionChangeAction.Add:
@ -104,7 +104,16 @@ namespace XenAdmin.TabPages
InsertActionRow(index, action);
break;
case CollectionChangeAction.Remove:
RemoveActionRow(action);
if (action != null)
{
RemoveActionRow(action);
}
else
{
var range = e.Element as List<ActionBase>;
if (range != null)
BuildRowList();
}
break;
case CollectionChangeAction.Refresh:
BuildRowList();

View File

@ -91,20 +91,24 @@ namespace XenAdmin.TabPages
private void UpdatesCollectionChanged(object sender, CollectionChangeEventArgs e)
{
Program.AssertOnEventThread();
if (e.Element == null)
{
// We take the null element to mean there has been a batch remove
Rebuild();
return;
}
Alert a = e.Element as Alert;
switch (e.Action)
{
case CollectionChangeAction.Add:
Rebuild(); // rebuild entire alert list to ensure filtering and sorting
break;
case CollectionChangeAction.Remove:
RemoveUpdateRow(a);
Alert a = e.Element as Alert;
if (a != null)
{
RemoveUpdateRow(a);
}
else
{
var range = e.Element as List<Alert>;
if (range != null)
Rebuild();
}
break;
}
}

View File

@ -230,19 +230,40 @@ namespace XenAdmin.TabPages
void History_CollectionChanged(object sender, CollectionChangeEventArgs e)
{
Program.BeginInvoke(Program.MainWindow, () =>
{
SrRefreshAction a = e.Element as SrRefreshAction;
if (a == null)
return;
{
SrRefreshAction a = e.Element as SrRefreshAction;
if (e.Action == CollectionChangeAction.Add)
a.Completed += a_Completed;
if (e.Action == CollectionChangeAction.Add)
{
if (a != null)
a.Completed += a_Completed;
else
return;
}
if (e.Action == CollectionChangeAction.Remove)
a.Completed -= a_Completed;
if (e.Action == CollectionChangeAction.Remove)
{
if (a != null)
{
a.Completed -= a_Completed;
}
else
{
var range = e.Element as List<SrRefreshAction>;
if (range != null)
{
foreach (var sra in range)
sra.Completed -= a_Completed;
}
else
{
return;
}
}
}
RefreshButtons();
});
RefreshButtons();
});
}
void a_Completed(ActionBase sender)

View File

@ -84,7 +84,10 @@ namespace XenAdmin.Core
{
var toRemove = FindAll(match);
base.RemoveAll(match);
toRemove.ForEach(item => OnCollectionChanged(new CollectionChangeEventArgs(CollectionChangeAction.Remove, item)));
if (toRemove.Count > 1)
OnCollectionChanged(new CollectionChangeEventArgs(CollectionChangeAction.Remove, toRemove));
else if (toRemove.Count == 1)
OnCollectionChanged(new CollectionChangeEventArgs(CollectionChangeAction.Remove, toRemove[0]));
return toRemove.Count;
}

View File

@ -46,10 +46,6 @@ namespace XenAdmin.Model
{
public class DockerContainers
{
static DockerContainers()
{
}
public static void InitDockerContainers()
{
Trace.Assert(InvokeHelper.Synchronizer != null);
@ -64,22 +60,31 @@ namespace XenAdmin.Model
private static void XenConnections_CollectionChanged(object sender, CollectionChangeEventArgs e)
{
InvokeHelper.BeginInvoke(() =>
{
IXenConnection connection = e.Element as IXenConnection;
if (connection == null)
return;
{
IXenConnection connection = e.Element as IXenConnection;
switch (e.Action)
{
case CollectionChangeAction.Add:
AddConnection(connection);
break;
switch (e.Action)
{
case CollectionChangeAction.Add:
if (connection != null)
AddConnection(connection);
break;
case CollectionChangeAction.Remove:
RemoveConnection(connection);
break;
}
});
case CollectionChangeAction.Remove:
if (connection != null)
{
RemoveConnection(connection);
}
else
{
var range = e.Element as List<IXenConnection>;
if (range != null)
foreach (var con in range)
RemoveConnection(con);
}
break;
}
});
}
private static CollectionChangeEventHandler CollectionChangedWithInvoke;
@ -106,9 +111,8 @@ namespace XenAdmin.Model
{
InvokeHelper.AssertOnEventThread();
Trace.Assert(e.Element is VM);
var vm = e.Element as VM;
Trace.Assert(vm != null, "The item changed is not a VM");
switch (e.Action)
{

View File

@ -74,24 +74,32 @@ namespace XenAdmin.Model
private static void XenConnections_CollectionChanged(object sender, CollectionChangeEventArgs e)
{
//Program.AssertOnEventThread();
InvokeHelper.BeginInvoke(() =>
{
IXenConnection connection = e.Element as IXenConnection;
if (connection == null)
return;
{
IXenConnection connection = e.Element as IXenConnection;
switch (e.Action)
{
case CollectionChangeAction.Add:
AddConnection(connection);
break;
switch (e.Action)
{
case CollectionChangeAction.Add:
if (connection != null)
AddConnection(connection);
break;
case CollectionChangeAction.Remove:
RemoveConnection(connection);
break;
}
});
case CollectionChangeAction.Remove:
if (connection != null)
{
RemoveConnection(connection);
}
else
{
var range = e.Element as List<IXenConnection>;
if (range != null)
foreach (var con in range)
RemoveConnection(con);
}
break;
}
});
}
private static CollectionChangeEventHandler CollectionChangedWithInvoke;

View File

@ -30,6 +30,7 @@
*/
using System;
using System.Collections.Generic;
using System.ComponentModel;
using XenAdmin.Network;
using XenAPI;
@ -93,11 +94,12 @@ namespace XenAdmin
return;
IXenConnection connection = e.Element as IXenConnection;
if (connection == null)
return;
if (e.Action == CollectionChangeAction.Add)
{
if (connection == null)
return;
connection.Cache.RegisterCollectionChanged<Pool>(PoolCollectionChangedWithInvoke);
connection.Cache.RegisterCollectionChanged<Host>(HostCollectionChangedWithInvoke);
connection.Cache.RegisterCollectionChanged<VM>(VMCollectionChangedWithInvoke);
@ -112,15 +114,32 @@ namespace XenAdmin
}
else if (e.Action == CollectionChangeAction.Remove)
{
connection.Cache.DeregisterCollectionChanged<Pool>(PoolCollectionChangedWithInvoke);
connection.Cache.DeregisterCollectionChanged<Host>(HostCollectionChangedWithInvoke);
connection.Cache.DeregisterCollectionChanged<VM>(VMCollectionChangedWithInvoke);
connection.Cache.DeregisterCollectionChanged<SR>(SRCollectionChangedWithInvoke);
connection.Cache.DeregisterCollectionChanged<VDI>(VDICollectionChangedWithInvoke);
connection.Cache.DeregisterCollectionChanged<XenAPI.Network>(NetworkCollectionChangedWithInvoke);
var range = new List<IXenConnection>();
if (connection != null)
{
range.Add(connection);
}
else
{
var r = e.Element as List<IXenConnection>;
if (r != null)
range = r;
else
return;
}
connection.XenObjectsUpdated -= connection_XenObjectsUpdated;
connection.ConnectionStateChanged -= connection_ConnectionStateChanged;
foreach (var con in range)
{
con.Cache.DeregisterCollectionChanged<Pool>(PoolCollectionChangedWithInvoke);
con.Cache.DeregisterCollectionChanged<Host>(HostCollectionChangedWithInvoke);
con.Cache.DeregisterCollectionChanged<VM>(VMCollectionChangedWithInvoke);
con.Cache.DeregisterCollectionChanged<SR>(SRCollectionChangedWithInvoke);
con.Cache.DeregisterCollectionChanged<VDI>(VDICollectionChangedWithInvoke);
con.Cache.DeregisterCollectionChanged<XenAPI.Network>(NetworkCollectionChangedWithInvoke);
con.XenObjectsUpdated -= connection_XenObjectsUpdated;
con.ConnectionStateChanged -= connection_ConnectionStateChanged;
}
}
MarkEventsReadyToFire(true);