mirror of
https://github.com/ckaczor/sqltoolsservice.git
synced 2026-01-14 01:25:40 -05:00
Add processors tab (#2166)
This commit is contained in:
@@ -63,7 +63,10 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectManagement
|
||||
StorageSpaceUsageInMB = prototype.StorageSpaceUsageInMB,
|
||||
Version = prototype.Version,
|
||||
MinServerMemory = prototype.MinServerMemory,
|
||||
MaxServerMemory = prototype.MaxServerMemory
|
||||
MaxServerMemory = prototype.MaxServerMemory,
|
||||
AutoProcessorAffinityMaskForAll = prototype.AutoProcessorAffinityMaskForAll,
|
||||
AutoProcessorAffinityIOMaskForAll = prototype.AutoProcessorAffinityIOMaskForAll,
|
||||
NumaNodes = prototype.NumaNodes
|
||||
};
|
||||
}
|
||||
return Task.FromResult(new InitializeViewResult { ViewInfo = this.serverViewInfo, Context = context });
|
||||
|
||||
@@ -4,6 +4,8 @@
|
||||
//
|
||||
#nullable disable
|
||||
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Microsoft.SqlTools.ServiceLayer.ObjectManagement
|
||||
{
|
||||
/// <summary>
|
||||
@@ -30,6 +32,9 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectManagement
|
||||
public string Version { get; set; }
|
||||
public NumericServerProperty MaxServerMemory { get; set; }
|
||||
public NumericServerProperty MinServerMemory { get; set; }
|
||||
public bool AutoProcessorAffinityMaskForAll { get; set; }
|
||||
public bool AutoProcessorAffinityIOMaskForAll { get; set; }
|
||||
public List<NumaNode> NumaNodes { get; set; }
|
||||
}
|
||||
|
||||
public class NumericServerProperty
|
||||
@@ -38,4 +43,16 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectManagement
|
||||
public int MinimumValue { get; set; }
|
||||
public int Value { get; set; }
|
||||
}
|
||||
public class NumaNode
|
||||
{
|
||||
public string NumaNodeId { get; set; }
|
||||
public List<ProcessorAffinity> Processors { get; set; }
|
||||
}
|
||||
|
||||
public class ProcessorAffinity
|
||||
{
|
||||
public string ProcessorId { get; set; }
|
||||
public bool Affinity { get; set; }
|
||||
public bool IOAffinity { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,221 @@
|
||||
//
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
//
|
||||
|
||||
using System;
|
||||
using System.Collections;
|
||||
using SMO = Microsoft.SqlServer.Management.Smo;
|
||||
|
||||
namespace Microsoft.SqlTools.ServiceLayer.ObjectManagement.ObjectTypes.Server
|
||||
{
|
||||
/// <summary>
|
||||
/// Class to manage affinity for 64 processors in an independent manner for I/O as well as processors
|
||||
/// </summary>
|
||||
internal sealed class AffinityManager
|
||||
{
|
||||
public const int MAX64CPU = 64;
|
||||
public const int MAX32CPU = 32;
|
||||
public const int MAX_IO_CPU_SUPPORTED = 64;
|
||||
|
||||
public BitArray initialIOAffinityArray = new BitArray(64, false);
|
||||
|
||||
private static string[] configFields = new string[]
|
||||
{
|
||||
"Minimum",
|
||||
"Maximum",
|
||||
"Dynamic",
|
||||
"ConfigValue",
|
||||
"RunValue"
|
||||
};
|
||||
#region class Affinity representing data related to each affinity mask
|
||||
/// <summary>
|
||||
/// The Affinity structure represents one row of the sys.configuration table for
|
||||
/// that particular affinity (affinity,affinty64 for processor or I/O).
|
||||
/// It also stores the old value of the affinity for optimizing server query.
|
||||
/// </summary>
|
||||
private class Affinity
|
||||
{
|
||||
private int affinityMaskCfg = 0;
|
||||
private int affinityMaskRun = 0;
|
||||
/// <summary>
|
||||
/// Affinity ConfigValue reflecting sys.configurations table
|
||||
/// </summary>
|
||||
public int AffinityMaskCfg { get { return affinityMaskCfg; } set { affinityMaskCfg = value; } }
|
||||
/// <summary>
|
||||
/// Affinity RunValue reflecting sys.configurations table
|
||||
/// </summary>
|
||||
public int AffinityMaskRun { get { return affinityMaskRun; } set { affinityMaskRun = value; } }
|
||||
|
||||
/// Reset the affinities to default values.
|
||||
/// </summary>
|
||||
public void Clear()
|
||||
{
|
||||
affinityMaskCfg = 0;
|
||||
affinityMaskRun = 0;
|
||||
}
|
||||
};
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// Generates a mask for masking the N processors
|
||||
/// </summary>
|
||||
/// <param name="numProcessors"> number of processors to mask</param>
|
||||
/// <returns>Mask for numProcessors</returns>
|
||||
private int GetMaskAllProcessors(int numProcessors)
|
||||
{
|
||||
if (numProcessors < MAX32CPU)
|
||||
{
|
||||
try
|
||||
{
|
||||
return System.Convert.ToInt32(Math.Pow(2, numProcessors) - 1);
|
||||
}
|
||||
catch (System.OverflowException)
|
||||
{
|
||||
return int.MaxValue;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Earlier code used int.MaxValue for return which was buggy
|
||||
// since in 2's compliment notation -1 is the one with all bits
|
||||
// set to 1. [anchals]
|
||||
return (int)-1;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Lets the caller know if only one CPU is selected. The processor number for the only set CPU is
|
||||
/// passed in. The method is optimized this way otherwise it needs to count the number of 1's in the
|
||||
/// affinity mask to see if only one CPU is selected.
|
||||
/// </summary>
|
||||
/// <param name="processorNumber">The CPU number for which affinity is to be set. Range: [0, 63]</param>
|
||||
/// <return>true: this is the last CPU which has affinity bit set;
|
||||
/// false: some other CPU than processorNumber is having affinity bit set.</return>
|
||||
public bool IsThisLastSelectedProcessor(int processorNumber)
|
||||
{
|
||||
if (processorNumber < MAX32CPU)
|
||||
{
|
||||
return (affinity.AffinityMaskCfg == (1 << processorNumber)) && (affinity64.AffinityMaskCfg == 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
return (affinity64.AffinityMaskCfg == (1 << (processorNumber - MAX32CPU))) && (affinity.AffinityMaskCfg == 0);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get affinity masks for first 32 and next 32 processors (total 64 processors) if the
|
||||
/// processor masks have been modified after being read from the server.
|
||||
/// </summary>
|
||||
/// <param name="affinityConfig">returns the affinity for first 32 processors. null if not changed</param>
|
||||
/// <param name="affinity64Config">return the affinity for CPUs 33-64. null if not changed.</param>
|
||||
public void GetAffinityMasksIfChanged(out int? affinityConfig, out int? affinity64Config)
|
||||
{
|
||||
affinityConfig = affinity64Config = null;
|
||||
affinityConfig = affinity.AffinityMaskCfg;
|
||||
affinity64Config = affinity64.AffinityMaskCfg;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Checks if automatic affinity is chosen. Happens when mask for all 64 processors is reset/0.
|
||||
/// Tells whether the CPU is in auto affinity mode or not. (i.e. all CPU mask bits are 0)
|
||||
/// </summary>
|
||||
/// <param name="basedOnConfigValue">true: use ConfigValue mask for test
|
||||
/// false: use RunValue mask for test.</param>
|
||||
/// <returns>true: The Affinity mode is set to "auto".; false: The affinity mode is not auto.</returns>
|
||||
public bool IsAutoAffinity(bool basedOnConfigValue)
|
||||
{
|
||||
return basedOnConfigValue ? (affinity.AffinityMaskCfg == 0 && affinity64.AffinityMaskCfg == 0)
|
||||
: (affinity.AffinityMaskRun == 0 && affinity64.AffinityMaskRun == 0);
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the affinity for CPU processorNumber as enabled or disabled.
|
||||
/// </summary>
|
||||
/// <param name="processorNumber">The CPU number for which affinity is queried. Range: [0, 63]</param>
|
||||
/// <return>true: affinity is enabled for the CPU; false: affinity disabled
|
||||
/// /// Note: if the function returns false then the SQL Server might be in auto mode also,
|
||||
/// as in auto mode all Processor Affinity Mask bits are 0.
|
||||
/// </return>
|
||||
public bool GetAffinity(int processorNumber, bool showConfigValues)
|
||||
{
|
||||
int aux = 0, mask = 0;
|
||||
if (processorNumber < MAX32CPU)
|
||||
{
|
||||
aux = showConfigValues ? affinity.AffinityMaskCfg : affinity.AffinityMaskRun;
|
||||
mask = 1 << processorNumber;
|
||||
}
|
||||
else
|
||||
{
|
||||
aux = showConfigValues ? affinity64.AffinityMaskCfg : affinity64.AffinityMaskRun;
|
||||
mask = 1 << (processorNumber - MAX32CPU);
|
||||
}
|
||||
|
||||
return (aux & mask) != 0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set the desired CPU's affinity.
|
||||
/// </summary>
|
||||
/// <param name="processorNumber">the CPU number for which affinity is set. Range: [0, 63] Must be valid.</param>
|
||||
/// <param name="affinityEnabled">
|
||||
/// true: set affinity bit for the CPU; false: reset CPU bit for the particular processor.
|
||||
/// Note: if false is passed then the SQL Server might be set in auto mode also,
|
||||
/// as in auto mode all Processor Affinity Mask bits are 0.
|
||||
/// </return>
|
||||
public void SetAffinity(int processorNumber, bool affinityEnabled)
|
||||
{
|
||||
int mask = 0;
|
||||
|
||||
if (processorNumber < MAX32CPU)
|
||||
{
|
||||
mask = 1 << processorNumber;
|
||||
if (affinityEnabled)
|
||||
{
|
||||
affinity.AffinityMaskCfg |= mask;
|
||||
}
|
||||
else
|
||||
{
|
||||
affinity.AffinityMaskCfg &= ~mask;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
mask = 1 << (processorNumber - MAX32CPU);
|
||||
if (affinityEnabled)
|
||||
{
|
||||
affinity64.AffinityMaskCfg |= mask;
|
||||
}
|
||||
else
|
||||
{
|
||||
affinity64.AffinityMaskCfg &= ~mask;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public void InitializeAffinity(SMO.ConfigProperty affinity, SMO.ConfigProperty affinity64)
|
||||
{
|
||||
this.affinity.AffinityMaskCfg = affinity.ConfigValue;
|
||||
this.affinity.AffinityMaskRun = affinity.RunValue;
|
||||
this.affinity64.AffinityMaskCfg = affinity64.ConfigValue;
|
||||
this.affinity64.AffinityMaskRun = affinity64.RunValue;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reset the affinities to default values.
|
||||
/// </summary>
|
||||
public void Clear()
|
||||
{
|
||||
initialIOAffinityArray = new BitArray(64, false);
|
||||
affinity.Clear();
|
||||
affinity64.Clear();
|
||||
}
|
||||
|
||||
private Affinity affinity = new Affinity(); // affinity mask for first 32 processors
|
||||
private Affinity affinity64 = new Affinity(); // affinity mask for next 32 (33-64) processors.
|
||||
};
|
||||
}
|
||||
@@ -5,10 +5,15 @@
|
||||
|
||||
using System;
|
||||
using Microsoft.SqlServer.Management.Smo;
|
||||
using SMO = Microsoft.SqlServer.Management.Smo;
|
||||
using Microsoft.SqlTools.ServiceLayer.Management;
|
||||
using Microsoft.SqlServer.Management.Common;
|
||||
using Microsoft.SqlTools.ServiceLayer.ServerConfigurations;
|
||||
using Microsoft.SqlTools.Utility;
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.SqlTools.ServiceLayer.ObjectManagement.ObjectTypes.Server;
|
||||
using System.Linq;
|
||||
using System.Collections;
|
||||
|
||||
namespace Microsoft.SqlTools.ServiceLayer.ObjectManagement
|
||||
{
|
||||
@@ -287,6 +292,45 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectManagement
|
||||
this.currentState.MinMemory = value;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public bool AutoProcessorAffinityMaskForAll
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.currentState.AutoProcessorAffinityMaskForAll;
|
||||
}
|
||||
set
|
||||
{
|
||||
this.currentState.AutoProcessorAffinityMaskForAll = value;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public bool AutoProcessorAffinityIOMaskForAll
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.currentState.AutoProcessorAffinityMaskForAll;
|
||||
}
|
||||
set
|
||||
{
|
||||
this.currentState.AutoProcessorAffinityMaskForAll = value;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public List<NumaNode> NumaNodes
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.currentState.NumaNodes;
|
||||
}
|
||||
set
|
||||
{
|
||||
this.currentState.NumaNodes = value;
|
||||
}
|
||||
|
||||
}
|
||||
#endregion
|
||||
|
||||
@@ -321,6 +365,37 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectManagement
|
||||
{
|
||||
Microsoft.SqlServer.Management.Smo.Server server = this.dataContainer.Server;
|
||||
bool changesMade = false;
|
||||
bool alterServerConfig = false;
|
||||
bool sendCPUAffinityBeforeIO = false;
|
||||
bool sendIOAffinityBeforeCPU = false;
|
||||
bool sentCpuAffinity = false;
|
||||
|
||||
sendCPUAffinityBeforeIO = this.CheckCPUAffinityBeforeIO(server);
|
||||
sendIOAffinityBeforeCPU = this.CheckIOAffinityBeforeCPU(server);
|
||||
alterServerConfig = this.CheckIOAffinityTsqlGenerated(server);
|
||||
if (!sendIOAffinityBeforeCPU)
|
||||
{
|
||||
SendDataForKJ(server);
|
||||
sentCpuAffinity = true;
|
||||
}
|
||||
|
||||
if (alterServerConfig)
|
||||
{
|
||||
try
|
||||
{
|
||||
server.Configuration.Alter((sendCPUAffinityBeforeIO && sendIOAffinityBeforeCPU));
|
||||
}
|
||||
finally
|
||||
{
|
||||
server.Configuration.Refresh();
|
||||
}
|
||||
}
|
||||
if (!sentCpuAffinity)
|
||||
{
|
||||
SendDataForKJ(server);
|
||||
}
|
||||
this.currentState.AffinityManagerProcessorMask.Clear();
|
||||
this.currentState.AffinityManagerIOMask.Clear();
|
||||
|
||||
changesMade = UpdateMemoryValues(this.dataContainer.Server);
|
||||
|
||||
@@ -349,6 +424,156 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectManagement
|
||||
}
|
||||
return changesMade;
|
||||
}
|
||||
|
||||
private bool CheckCPUAffinityBeforeIO(SMO.Server smoServer)
|
||||
{
|
||||
for (int i = 0; i < this.NumaNodes.Count; i++)
|
||||
{
|
||||
SMO.NumaNode nNode = smoServer.AffinityInfo.NumaNodes[i];
|
||||
for (int cpuCount = 0; cpuCount < this.NumaNodes[i].Processors.Count; cpuCount++)
|
||||
{
|
||||
SMO.Cpu cpu = nNode.Cpus[cpuCount];
|
||||
if (cpu.GroupID == 0)
|
||||
{
|
||||
if (cpu.AffinityMask == this.NumaNodes[i].Processors[cpuCount].IOAffinity && cpu.AffinityMask)
|
||||
{
|
||||
//if Current IO affinity is equal to initial cpu.Affinity then script Cpu Affinity first
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private bool CheckIOAffinityBeforeCPU(SMO.Server smoServer)
|
||||
{
|
||||
for (int i = 0; i < this.NumaNodes.Count; i++)
|
||||
{
|
||||
SMO.NumaNode nNode = smoServer.AffinityInfo.NumaNodes[i];
|
||||
for (int cpuCount = 0; cpuCount < this.NumaNodes[i].Processors.Count; cpuCount++)
|
||||
{
|
||||
SMO.Cpu cpu = nNode.Cpus[cpuCount];
|
||||
if (cpu.GroupID == 0)
|
||||
{
|
||||
if (this.currentState.AffinityManagerIOMask.initialIOAffinityArray[cpu.ID] == this.NumaNodes[i].Processors[cpuCount].Affinity && this.currentState.AffinityManagerIOMask.initialIOAffinityArray[cpu.ID])
|
||||
{
|
||||
//if Current IO affinity is equal to initial cpu.Affinity then script Cpu Affinity first
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
/// <summary>
|
||||
/// This will send data for KJ specific things
|
||||
/// Also Checks if Alter needs to be generated
|
||||
/// </summary>
|
||||
private void SendDataForKJ(SMO.Server smoServer)
|
||||
{
|
||||
BitArray finalCpuAffinity = new BitArray(64, false);
|
||||
bool sendAffinityInfoAlter = false;
|
||||
|
||||
if (this.AutoProcessorAffinityMaskForAll)
|
||||
{
|
||||
if (smoServer.AffinityInfo.AffinityType != Microsoft.SqlServer.Management.Smo.AffinityType.Auto)
|
||||
{
|
||||
smoServer.AffinityInfo.AffinityType = Microsoft.SqlServer.Management.Smo.AffinityType.Auto;
|
||||
sendAffinityInfoAlter = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (smoServer.AffinityInfo.AffinityType != Microsoft.SqlServer.Management.Smo.AffinityType.Manual)
|
||||
{
|
||||
smoServer.AffinityInfo.AffinityType = Microsoft.SqlServer.Management.Smo.AffinityType.Manual;
|
||||
sendAffinityInfoAlter = true;
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < this.NumaNodes.Count; i++)
|
||||
{
|
||||
SMO.NumaNode node = smoServer.AffinityInfo.NumaNodes[i];
|
||||
for (int cpuCount = 0; cpuCount < this.NumaNodes[i].Processors.Count; cpuCount++)
|
||||
{
|
||||
SMO.Cpu cpu = node.Cpus[cpuCount];
|
||||
if (this.NumaNodes[i].Processors[cpuCount].Affinity != cpu.AffinityMask)
|
||||
{
|
||||
sendAffinityInfoAlter = true;
|
||||
if (!this.AutoProcessorAffinityMaskForAll)
|
||||
{
|
||||
cpu.AffinityMask = this.NumaNodes[i].Processors[cpuCount].Affinity;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (sendAffinityInfoAlter)
|
||||
{
|
||||
try
|
||||
{
|
||||
smoServer.AffinityInfo.Alter();
|
||||
smoServer.Configuration.Alter();
|
||||
}
|
||||
finally
|
||||
{
|
||||
smoServer.AffinityInfo.Refresh();
|
||||
smoServer.Configuration.Refresh();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private bool CheckIOAffinityTsqlGenerated(SMO.Server smoServer)
|
||||
{
|
||||
bool sendAlter = false;
|
||||
bool send64AffinityIOAlter = false;
|
||||
BitArray finalCpuIOAffinity = new BitArray(64, false);
|
||||
for (int i = 0; i < this.NumaNodes.Count; i++)
|
||||
{
|
||||
SMO.NumaNode nNode = smoServer.AffinityInfo.NumaNodes[i];
|
||||
for (int cpuCount = 0; cpuCount < this.NumaNodes[i].Processors.Count; cpuCount++)
|
||||
{
|
||||
SMO.Cpu cpu = nNode.Cpus[cpuCount];
|
||||
if (cpu.GroupID == 0)
|
||||
{
|
||||
finalCpuIOAffinity[cpu.ID] = this.NumaNodes[i].Processors[cpuCount].IOAffinity;
|
||||
if (this.currentState.AffinityManagerIOMask.initialIOAffinityArray[cpu.ID] != finalCpuIOAffinity[cpu.ID])
|
||||
{
|
||||
if (cpu.ID < AffinityManager.MAX32CPU)
|
||||
{
|
||||
sendAlter = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
send64AffinityIOAlter = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (sendAlter || send64AffinityIOAlter)
|
||||
{
|
||||
int[] intArray = new int[2];
|
||||
finalCpuIOAffinity.CopyTo(intArray, 0);
|
||||
if (sendAlter)
|
||||
{
|
||||
smoServer.Configuration.AffinityIOMask.ConfigValue = intArray[0];
|
||||
}
|
||||
if (send64AffinityIOAlter)
|
||||
{
|
||||
smoServer.Configuration.Affinity64IOMask.ConfigValue = intArray[1];
|
||||
}
|
||||
//update current state initialIO after update
|
||||
if (this.currentState.AffinityManagerIOMask.initialIOAffinityArray != finalCpuIOAffinity)
|
||||
{
|
||||
this.currentState.AffinityManagerIOMask.initialIOAffinityArray = finalCpuIOAffinity;
|
||||
}
|
||||
}
|
||||
return (sendAlter || send64AffinityIOAlter);
|
||||
}
|
||||
#endregion
|
||||
|
||||
public void ApplyInfoToPrototype(ServerInfo serverInfo)
|
||||
@@ -373,6 +598,9 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectManagement
|
||||
this.StorageSpaceUsageInMB = (int)(serverInfo.StorageSpaceUsageInMB);
|
||||
this.MaxServerMemory = serverInfo.MaxServerMemory;
|
||||
this.MinServerMemory = serverInfo.MinServerMemory;
|
||||
this.AutoProcessorAffinityMaskForAll = serverInfo.AutoProcessorAffinityMaskForAll;
|
||||
this.AutoProcessorAffinityIOMaskForAll = serverInfo.AutoProcessorAffinityIOMaskForAll;
|
||||
this.NumaNodes = serverInfo.NumaNodes.ToList();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -403,19 +631,53 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectManagement
|
||||
private string serviceTier = String.Empty;
|
||||
private int reservedStorageSizeMB = 0;
|
||||
private int storageSpaceUsageInMB = 0;
|
||||
|
||||
private NumericServerProperty minMemory;
|
||||
private NumericServerProperty maxMemory;
|
||||
private bool autoProcessorAffinityMaskForAll = false;
|
||||
private bool autoProcessorAffinityIOMaskForAll = false;
|
||||
private List<NumaNode> numaNodes = new List<NumaNode>();
|
||||
|
||||
private bool initialized = false;
|
||||
private Server server;
|
||||
private CDataContainer context;
|
||||
private ServerConfigService configService;
|
||||
private AffinityManager affinityManagerIOMask;
|
||||
private AffinityManager affinityManagerProcessorMask;
|
||||
|
||||
private bool isYukonOrLater = false;
|
||||
private bool isSqlServer64Bit;
|
||||
private bool isIOAffinitySupported = false;
|
||||
|
||||
ConfigProperty serverMaxMemoryProperty;
|
||||
ConfigProperty serverMinMemoryProperty;
|
||||
#endregion
|
||||
|
||||
public AffinityManager AffinityManagerIOMask
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.affinityManagerIOMask;
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
this.affinityManagerIOMask = value;
|
||||
}
|
||||
}
|
||||
|
||||
public AffinityManager AffinityManagerProcessorMask
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.affinityManagerProcessorMask;
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
this.affinityManagerProcessorMask = value;
|
||||
}
|
||||
}
|
||||
|
||||
#region Properties
|
||||
|
||||
// General properties
|
||||
@@ -835,11 +1097,11 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectManagement
|
||||
set
|
||||
{
|
||||
if (this.initialized)
|
||||
{
|
||||
{
|
||||
Logger.Error(SR.PropertyNotInitialized("MinMemory"));
|
||||
}
|
||||
|
||||
this.minMemory = value;
|
||||
this.minMemory = value;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -866,6 +1128,75 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectManagement
|
||||
}
|
||||
}
|
||||
|
||||
public bool AutoProcessorAffinityMaskForAll
|
||||
{
|
||||
get
|
||||
{
|
||||
if (!this.initialized)
|
||||
{
|
||||
LoadData();
|
||||
}
|
||||
|
||||
return this.autoProcessorAffinityMaskForAll;
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
if (this.initialized)
|
||||
{
|
||||
Logger.Error(SR.PropertyNotInitialized("AutoProcessorAffinityMaskForAll"));
|
||||
}
|
||||
|
||||
this.autoProcessorAffinityMaskForAll = value;
|
||||
}
|
||||
}
|
||||
|
||||
public bool AutoProcessorAffinityIOMaskForAll
|
||||
{
|
||||
get
|
||||
{
|
||||
if (!this.initialized)
|
||||
{
|
||||
LoadData();
|
||||
}
|
||||
|
||||
return this.autoProcessorAffinityIOMaskForAll;
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
if (this.initialized)
|
||||
{
|
||||
Logger.Error(SR.PropertyNotInitialized("AutoProcessorAffinityIOMaskForAll"));
|
||||
}
|
||||
|
||||
this.autoProcessorAffinityIOMaskForAll = value;
|
||||
}
|
||||
}
|
||||
|
||||
public List<NumaNode> NumaNodes
|
||||
{
|
||||
get
|
||||
{
|
||||
if (!this.initialized)
|
||||
{
|
||||
LoadData();
|
||||
}
|
||||
|
||||
return this.numaNodes;
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
if (this.initialized)
|
||||
{
|
||||
Logger.Error(SR.PropertyNotInitialized("NumaNodes"));
|
||||
}
|
||||
|
||||
this.numaNodes = value;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public Microsoft.SqlServer.Management.Smo.Server Server
|
||||
{
|
||||
@@ -904,10 +1235,15 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectManagement
|
||||
this.context = context;
|
||||
this.configService = service;
|
||||
this.isYukonOrLater = (this.server.Information.Version.Major >= 9);
|
||||
this.isSqlServer64Bit = (this.server.Edition.Contains("(64 - bit)"));
|
||||
this.affinityManagerIOMask = new AffinityManager();
|
||||
this.affinityManagerProcessorMask = new AffinityManager();
|
||||
this.serverMaxMemoryProperty = this.configService.GetServerSmoConfig(server, this.configService.MaxServerMemoryPropertyNumber);
|
||||
this.serverMinMemoryProperty = this.configService.GetServerSmoConfig(server, this.configService.MinServerMemoryPropertyNumber);
|
||||
this.minMemory = new NumericServerProperty();
|
||||
this.maxMemory = new NumericServerProperty();
|
||||
this.NumaNodes = new List<NumaNode>();
|
||||
|
||||
LoadData();
|
||||
}
|
||||
|
||||
@@ -939,6 +1275,9 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectManagement
|
||||
result.version = this.version;
|
||||
result.maxMemory = this.maxMemory;
|
||||
result.minMemory = this.minMemory;
|
||||
result.autoProcessorAffinityMaskForAll = this.autoProcessorAffinityMaskForAll;
|
||||
result.autoProcessorAffinityIOMaskForAll = this.autoProcessorAffinityIOMaskForAll;
|
||||
result.numaNodes = this.numaNodes;
|
||||
result.server = this.server;
|
||||
return result;
|
||||
}
|
||||
@@ -965,6 +1304,19 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectManagement
|
||||
this.serviceTier = server.ServiceTier;
|
||||
this.storageSpaceUsageInMB = server.UsedStorageSizeMB;
|
||||
LoadMemoryProperties();
|
||||
try
|
||||
{
|
||||
this.affinityManagerIOMask.InitializeAffinity(this.server.Configuration.AffinityIOMask, this.server.Configuration.Affinity64IOMask);
|
||||
this.isIOAffinitySupported = true;
|
||||
}
|
||||
catch
|
||||
{
|
||||
this.isIOAffinitySupported = false;
|
||||
}
|
||||
this.affinityManagerProcessorMask.InitializeAffinity(this.server.Configuration.AffinityMask, this.server.Configuration.Affinity64Mask);
|
||||
|
||||
this.numaNodes = GetNumaNodes();
|
||||
GetAutoProcessorsAffinity();
|
||||
}
|
||||
|
||||
private void LoadMemoryProperties()
|
||||
@@ -977,6 +1329,50 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectManagement
|
||||
this.minMemory.MaximumValue = serverMinMemoryProperty.Maximum;
|
||||
this.minMemory.MinimumValue = serverMinMemoryProperty.Minimum;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get affinity masks for first 32 and next 32 processors (total 64 processors) if the
|
||||
/// processor masks have been modified after being read from the server.
|
||||
/// </summary>
|
||||
/// <param name="affinityConfig">returns the affinity for first 32 processors. null if not changed</param>
|
||||
/// <param name="affinity64Config">return the affinity for CPUs 33-64. null if not changed.</param>
|
||||
private List<NumaNode> GetNumaNodes()
|
||||
{
|
||||
List<NumaNode> results = new List<NumaNode>();
|
||||
foreach (SMO.NumaNode node in this.server.AffinityInfo.NumaNodes)
|
||||
{
|
||||
var processors = new List<ProcessorAffinity>();
|
||||
foreach (SMO.Cpu cpu in node.Cpus)
|
||||
{
|
||||
if (cpu.GroupID == 0)
|
||||
{
|
||||
var affinityIO = this.AffinityManagerIOMask.GetAffinity(cpu.ID, true);
|
||||
if (!cpu.AffinityMask && this.isIOAffinitySupported && affinityIO) // if it's false then check if io affinity is checked
|
||||
{
|
||||
this.AffinityManagerIOMask.initialIOAffinityArray[cpu.ID] = true;
|
||||
}
|
||||
|
||||
// get affinityIO info if group id is 0
|
||||
processors.Add(new ProcessorAffinity() { ProcessorId = cpu.ID.ToString(), Affinity = cpu.AffinityMask, IOAffinity = affinityIO });
|
||||
}
|
||||
}
|
||||
var result = new NumaNode() { NumaNodeId = node.ID.ToString(), Processors = processors };
|
||||
results.Add(result);
|
||||
}
|
||||
return results;
|
||||
}
|
||||
|
||||
private void GetAutoProcessorsAffinity()
|
||||
{
|
||||
if (this.server.AffinityInfo.AffinityType == Microsoft.SqlServer.Management.Smo.AffinityType.Auto)
|
||||
{
|
||||
this.autoProcessorAffinityMaskForAll = this.autoProcessorAffinityIOMaskForAll = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
this.autoProcessorAffinityMaskForAll = this.autoProcessorAffinityIOMaskForAll = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -87,9 +87,13 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.ObjectManagement
|
||||
MaxServerMemory = result.MaxServerMemory
|
||||
};
|
||||
|
||||
// original memory settings
|
||||
var originalMinMemory = result.MinServerMemory.Value;
|
||||
var originalMaxMemory = result.MaxServerMemory.Value;
|
||||
|
||||
// Change memory settings
|
||||
serverInfo.MinServerMemory.Value = 10;
|
||||
serverInfo.MaxServerMemory.Value = 500;
|
||||
serverInfo.MinServerMemory.Value = serverInfo.MinServerMemory.MinimumValue;
|
||||
serverInfo.MaxServerMemory.Value = serverInfo.MaxServerMemory.MaximumValue;
|
||||
|
||||
Assert.That(result.MinServerMemory.Value, Is.Not.EqualTo(serverInfo.MinServerMemory.Value), "Server property should not be equal after update");
|
||||
Assert.That(result.MaxServerMemory.Value, Is.Not.EqualTo(serverInfo.MaxServerMemory.Value), "Server property should not be equal after update");
|
||||
@@ -100,6 +104,57 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.ObjectManagement
|
||||
Assert.That(result, Is.Not.Null);
|
||||
Assert.That(result.MinServerMemory.Value, Is.EqualTo(serverInfo.MinServerMemory.Value), "Server property should be equal after update");
|
||||
Assert.That(result.MaxServerMemory.Value, Is.EqualTo(serverInfo.MaxServerMemory.Value), "Server property should be equal after update");
|
||||
|
||||
// Reset to original values
|
||||
serverInfo.MinServerMemory.Value = originalMinMemory;
|
||||
serverInfo.MaxServerMemory.Value = originalMaxMemory;
|
||||
await ObjectManagementTestUtils.SaveObject(requestParams, serverInfo);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test Processors for Sql Server
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task GetProcessorsProperties()
|
||||
{
|
||||
var connectionResult = await LiveConnectionHelper.InitLiveConnectionInfoAsync("master", serverType: TestServerType.OnPrem);
|
||||
using (SqlConnection sqlConn = ConnectionService.OpenSqlConnection(connectionResult.ConnectionInfo))
|
||||
{
|
||||
var server = new Server(new ServerConnection(sqlConn));
|
||||
var serverHandler = new ServerHandler(ConnectionService.Instance);
|
||||
|
||||
var requestParams = ObjectManagementTestUtils.GetInitializeViewRequestParams(connectionResult.ConnectionInfo.OwnerUri, "master", true, SqlObjectType.Server, "", "");
|
||||
var result = (ServerInfo)(await serverHandler.InitializeObjectView(requestParams)).ViewInfo.ObjectInfo;
|
||||
ServerInfo serverInfo = new ServerInfo()
|
||||
{
|
||||
Name = result.Name,
|
||||
HardwareGeneration = result.HardwareGeneration,
|
||||
Language = result.Language,
|
||||
MemoryInMB = result.MemoryInMB,
|
||||
OperatingSystem = result.OperatingSystem,
|
||||
Platform = result.Platform,
|
||||
Processors = result.Processors,
|
||||
IsClustered = result.IsClustered,
|
||||
IsHadrEnabled = result.IsHadrEnabled,
|
||||
IsPolyBaseInstalled = result.IsPolyBaseInstalled,
|
||||
IsXTPSupported = result.IsXTPSupported,
|
||||
Product = result.Product,
|
||||
ReservedStorageSizeMB = result.ReservedStorageSizeMB,
|
||||
RootDirectory = result.RootDirectory,
|
||||
ServerCollation = result.ServerCollation,
|
||||
ServiceTier = result.ServiceTier,
|
||||
StorageSpaceUsageInMB = result.StorageSpaceUsageInMB,
|
||||
Version = result.Version,
|
||||
MinServerMemory = result.MinServerMemory,
|
||||
MaxServerMemory = result.MaxServerMemory,
|
||||
AutoProcessorAffinityMaskForAll = result.AutoProcessorAffinityMaskForAll,
|
||||
AutoProcessorAffinityIOMaskForAll = result.AutoProcessorAffinityIOMaskForAll
|
||||
};
|
||||
|
||||
Assert.That(result, Is.Not.Null);
|
||||
Assert.That(result.AutoProcessorAffinityIOMaskForAll,Is.True, "Auto affinity should be default");
|
||||
Assert.That(result.AutoProcessorAffinityMaskForAll, Is.True, "Auto affinity should be default");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user