mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-02-17 02:51:36 -05:00
Add processors tab (#23634)
Co-authored-by: Cory Rivera <corivera@microsoft.com>
This commit is contained in:
@@ -30,6 +30,7 @@ export const AlterDatabaseRoleDocUrl = 'https://learn.microsoft.com/sql/t-sql/st
|
|||||||
export const CreateDatabaseDocUrl = 'https://learn.microsoft.com/sql/t-sql/statements/create-database-transact-sql';
|
export const CreateDatabaseDocUrl = 'https://learn.microsoft.com/sql/t-sql/statements/create-database-transact-sql';
|
||||||
export const ViewGeneralServerPropertiesDocUrl = 'https://learn.microsoft.com/sql/t-sql/functions/serverproperty-transact-sql';
|
export const ViewGeneralServerPropertiesDocUrl = 'https://learn.microsoft.com/sql/t-sql/functions/serverproperty-transact-sql';
|
||||||
export const ViewMemoryServerPropertiesDocUrl = 'https://learn.microsoft.com/sql/database-engine/configure-windows/server-properties-memory-page';
|
export const ViewMemoryServerPropertiesDocUrl = 'https://learn.microsoft.com/sql/database-engine/configure-windows/server-properties-memory-page';
|
||||||
|
export const ViewProcessorsServerPropertiesDocUrl = 'https://learn.microsoft.com/sql/database-engine/configure-windows/server-properties-processors-page';
|
||||||
export const DetachDatabaseDocUrl = 'https://go.microsoft.com/fwlink/?linkid=2240322';
|
export const DetachDatabaseDocUrl = 'https://go.microsoft.com/fwlink/?linkid=2240322';
|
||||||
export const DatabaseGeneralPropertiesDocUrl = 'https://learn.microsoft.com/sql/relational-databases/databases/database-properties-general-page';
|
export const DatabaseGeneralPropertiesDocUrl = 'https://learn.microsoft.com/sql/relational-databases/databases/database-properties-general-page';
|
||||||
export const DatabaseOptionsPropertiesDocUrl = 'https://learn.microsoft.com/sql/relational-databases/databases/database-properties-options-page'
|
export const DatabaseOptionsPropertiesDocUrl = 'https://learn.microsoft.com/sql/relational-databases/databases/database-properties-options-page'
|
||||||
|
|||||||
@@ -495,6 +495,22 @@ export interface AzureEditionDetails {
|
|||||||
editionOptions: OptionsCollection;
|
editionOptions: OptionsCollection;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface ProcessorAffinity {
|
||||||
|
processorId: string;
|
||||||
|
affinity: boolean;
|
||||||
|
ioAffinity: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface NumaNode {
|
||||||
|
numaNodeId: string
|
||||||
|
processors: ProcessorAffinity[]
|
||||||
|
}
|
||||||
|
|
||||||
|
export enum AffinityType {
|
||||||
|
ProcessorAffinity = 1,
|
||||||
|
IOAffinity = 2,
|
||||||
|
}
|
||||||
|
|
||||||
export interface Server extends ObjectManagement.SqlObject {
|
export interface Server extends ObjectManagement.SqlObject {
|
||||||
hardwareGeneration: string;
|
hardwareGeneration: string;
|
||||||
language: string;
|
language: string;
|
||||||
@@ -515,6 +531,9 @@ export interface Server extends ObjectManagement.SqlObject {
|
|||||||
storageSpaceUsageInMB: number;
|
storageSpaceUsageInMB: number;
|
||||||
minServerMemory: NumericServerProperty;
|
minServerMemory: NumericServerProperty;
|
||||||
maxServerMemory: NumericServerProperty;
|
maxServerMemory: NumericServerProperty;
|
||||||
|
autoProcessorAffinityMaskForAll: boolean;
|
||||||
|
autoProcessorAffinityIOMaskForAll: boolean;
|
||||||
|
numaNodes: NumaNode[];
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface NumericServerProperty {
|
export interface NumericServerProperty {
|
||||||
|
|||||||
@@ -277,7 +277,15 @@ export const StorageSpaceUsageInMBText = localize('objectManagement.storageSpace
|
|||||||
export const VersionText = localize('objectManagement.versionText', "Version");
|
export const VersionText = localize('objectManagement.versionText', "Version");
|
||||||
export const minServerMemoryText = localize('objectManagement.minServerMemoryText', "Minimum Server Memory (MB)");
|
export const minServerMemoryText = localize('objectManagement.minServerMemoryText', "Minimum Server Memory (MB)");
|
||||||
export const maxServerMemoryText = localize('objectManagement.maxServerMemoryText', "Maximum Server Memory (MB)");
|
export const maxServerMemoryText = localize('objectManagement.maxServerMemoryText', "Maximum Server Memory (MB)");
|
||||||
export const serverMemoryMaxLowerThanMinInputError: string = localize('objectManagement.serverMemoryMaxLowerThanMinInputError', "Maximum server memory cannot be lower than minimum server memory")
|
export const autoSetProcessorAffinityMaskForAllText = localize('objectManagement.autoSetProcessorAffinityMaskForAll', "Automatically set processor affinity mask for all processors");
|
||||||
|
export const autoSetProcessorAffinityIOMaskForAllText = localize('objectManagement.autoSetProcessorAffinityIOMaskForAll', "Automatically set I/O affinity mask for all processors");
|
||||||
|
export const processorColumnText = localize('objectManagement.processorColumn', "Processor");
|
||||||
|
export const processorAffinityColumnText = localize('objectManagement.processorAffinityColumn', "Processor Affinity");
|
||||||
|
export const processorIOAffinityColumnText = localize('objectManagement.processorIOAffinityColumn', "I/O Affinity");
|
||||||
|
export const processorLabel = localize('objectManagement.processorLabel', "Processor Affinity Table");
|
||||||
|
export const serverMemoryMaxLowerThanMinInputError: string = localize('objectManagement.serverMemoryMaxLowerThanMinInputError', "Maximum server memory cannot be lower than minimum server memory");
|
||||||
|
export const serverNumaNodeLabel = (value: string) => localize('objectManagement.serverNumaNodeLabel', "Numa Node {0}", value);
|
||||||
|
export const serverCPULabel = (value: string) => localize('objectManagement.serverCPULabel', "CPU {0}", value);
|
||||||
|
|
||||||
//Database properties Dialog
|
//Database properties Dialog
|
||||||
export const LastDatabaseBackupText = localize('objectManagement.lastDatabaseBackup', "Last Database Backup");
|
export const LastDatabaseBackupText = localize('objectManagement.lastDatabaseBackup', "Last Database Backup");
|
||||||
|
|||||||
@@ -4,10 +4,11 @@
|
|||||||
*--------------------------------------------------------------------------------------------*/
|
*--------------------------------------------------------------------------------------------*/
|
||||||
import * as azdata from 'azdata';
|
import * as azdata from 'azdata';
|
||||||
import { ObjectManagementDialogBase, ObjectManagementDialogOptions } from './objectManagementDialogBase';
|
import { ObjectManagementDialogBase, ObjectManagementDialogOptions } from './objectManagementDialogBase';
|
||||||
|
import { DefaultColumnCheckboxWidth } from '../../ui/dialogBase';
|
||||||
import { IObjectManagementService } from 'mssql';
|
import { IObjectManagementService } from 'mssql';
|
||||||
import * as localizedConstants from '../localizedConstants';
|
import * as localizedConstants from '../localizedConstants';
|
||||||
import { ViewGeneralServerPropertiesDocUrl, ViewMemoryServerPropertiesDocUrl } from '../constants';
|
import { ViewGeneralServerPropertiesDocUrl, ViewMemoryServerPropertiesDocUrl, ViewProcessorsServerPropertiesDocUrl } from '../constants';
|
||||||
import { Server, ServerViewInfo } from '../interfaces';
|
import { Server, ServerViewInfo, NumaNode, AffinityType } from '../interfaces';
|
||||||
|
|
||||||
export class ServerPropertiesDialog extends ObjectManagementDialogBase<Server, ServerViewInfo> {
|
export class ServerPropertiesDialog extends ObjectManagementDialogBase<Server, ServerViewInfo> {
|
||||||
private generalTab: azdata.Tab;
|
private generalTab: azdata.Tab;
|
||||||
@@ -40,6 +41,11 @@ export class ServerPropertiesDialog extends ObjectManagementDialogBase<Server, S
|
|||||||
private maxServerMemoryInput: azdata.InputBoxComponent;
|
private maxServerMemoryInput: azdata.InputBoxComponent;
|
||||||
private engineEdition: azdata.DatabaseEngineEdition;
|
private engineEdition: azdata.DatabaseEngineEdition;
|
||||||
|
|
||||||
|
private processorsTab: azdata.Tab;
|
||||||
|
private readonly processorsTabId: string = 'processorsId';
|
||||||
|
private processorsSection: azdata.GroupContainer;
|
||||||
|
private autoSetProcessorAffinityMaskForAllCheckbox: azdata.CheckBoxComponent;
|
||||||
|
private autoSetProcessorIOAffinityMaskForAllCheckbox: azdata.CheckBoxComponent;
|
||||||
private activeTabId: string;
|
private activeTabId: string;
|
||||||
|
|
||||||
constructor(objectManagementService: IObjectManagementService, options: ObjectManagementDialogOptions) {
|
constructor(objectManagementService: IObjectManagementService, options: ObjectManagementDialogOptions) {
|
||||||
@@ -55,6 +61,8 @@ export class ServerPropertiesDialog extends ObjectManagementDialogBase<Server, S
|
|||||||
break;
|
break;
|
||||||
case this.memoryTabId:
|
case this.memoryTabId:
|
||||||
helpUrl = ViewMemoryServerPropertiesDocUrl;
|
helpUrl = ViewMemoryServerPropertiesDocUrl;
|
||||||
|
case this.processorsTabId:
|
||||||
|
helpUrl = ViewProcessorsServerPropertiesDocUrl;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -71,7 +79,8 @@ export class ServerPropertiesDialog extends ObjectManagementDialogBase<Server, S
|
|||||||
this.engineEdition = serverInfo.engineEditionId;
|
this.engineEdition = serverInfo.engineEditionId;
|
||||||
this.initializeGeneralSection();
|
this.initializeGeneralSection();
|
||||||
this.initializeMemorySection();
|
this.initializeMemorySection();
|
||||||
const serverPropertiesTabGroup = { title: '', tabs: [this.generalTab, this.memoryTab] };
|
this.initializeProcessorsSection();
|
||||||
|
const serverPropertiesTabGroup = { title: '', tabs: [this.generalTab, this.memoryTab, this.processorsTab] };
|
||||||
const serverPropertiesTabbedPannel = this.modelView.modelBuilder.tabbedPanel()
|
const serverPropertiesTabbedPannel = this.modelView.modelBuilder.tabbedPanel()
|
||||||
.withTabs([serverPropertiesTabGroup])
|
.withTabs([serverPropertiesTabGroup])
|
||||||
.withProps({
|
.withProps({
|
||||||
@@ -269,6 +278,7 @@ export class ServerPropertiesDialog extends ObjectManagementDialogBase<Server, S
|
|||||||
enabled: isEnabled,
|
enabled: isEnabled,
|
||||||
max: this.objectInfo.minServerMemory.maximumValue,
|
max: this.objectInfo.minServerMemory.maximumValue,
|
||||||
min: this.objectInfo.minServerMemory.minimumValue,
|
min: this.objectInfo.minServerMemory.minimumValue,
|
||||||
|
value: this.objectInfo.minServerMemory.value.toString(),
|
||||||
required: true
|
required: true
|
||||||
};
|
};
|
||||||
this.minServerMemoryInput = this.createInputBox(async (newValue) => {
|
this.minServerMemoryInput = this.createInputBox(async (newValue) => {
|
||||||
@@ -282,6 +292,7 @@ export class ServerPropertiesDialog extends ObjectManagementDialogBase<Server, S
|
|||||||
enabled: isEnabled,
|
enabled: isEnabled,
|
||||||
max: this.objectInfo.maxServerMemory.maximumValue,
|
max: this.objectInfo.maxServerMemory.maximumValue,
|
||||||
min: this.objectInfo.maxServerMemory.minimumValue,
|
min: this.objectInfo.maxServerMemory.minimumValue,
|
||||||
|
value: this.objectInfo.maxServerMemory.value.toString(),
|
||||||
required: true
|
required: true
|
||||||
};
|
};
|
||||||
this.maxServerMemoryInput = this.createInputBox(async (newValue) => {
|
this.maxServerMemoryInput = this.createInputBox(async (newValue) => {
|
||||||
@@ -304,4 +315,120 @@ export class ServerPropertiesDialog extends ObjectManagementDialogBase<Server, S
|
|||||||
}
|
}
|
||||||
return errors;
|
return errors;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private initializeProcessorsSection(): void {
|
||||||
|
const isEnabled = this.engineEdition !== azdata.DatabaseEngineEdition.SqlManagedInstance;
|
||||||
|
let nodes: NumaNode[] = this.objectInfo.numaNodes;
|
||||||
|
let nodeTableList: azdata.TableComponent[] = [];
|
||||||
|
let tableGroups: azdata.GroupContainer[] = [];
|
||||||
|
for (let node of nodes) {
|
||||||
|
let table = this.createProcessorTable(node);
|
||||||
|
nodeTableList.push(table);
|
||||||
|
tableGroups.push(this.createGroup(localizedConstants.serverNumaNodeLabel(node.numaNodeId), [table], true));
|
||||||
|
}
|
||||||
|
this.autoSetProcessorAffinityMaskForAllCheckbox = this.createCheckbox(localizedConstants.autoSetProcessorAffinityMaskForAllText, async (newValue) => {
|
||||||
|
this.objectInfo.autoProcessorAffinityMaskForAll = newValue;
|
||||||
|
for (let table of nodeTableList) {
|
||||||
|
let newData = table.data;
|
||||||
|
for (let i = 0; i < newData.length; i++) {
|
||||||
|
if (newValue) {
|
||||||
|
// if affinity mask for all is checked, then uncheck the individual processors
|
||||||
|
newData[i][AffinityType.ProcessorAffinity] = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
await this.setTableData(table, newData);
|
||||||
|
}
|
||||||
|
}, this.objectInfo.autoProcessorAffinityMaskForAll, isEnabled);
|
||||||
|
|
||||||
|
this.autoSetProcessorIOAffinityMaskForAllCheckbox = this.createCheckbox(localizedConstants.autoSetProcessorAffinityIOMaskForAllText, async (newValue) => {
|
||||||
|
this.objectInfo.autoProcessorAffinityIOMaskForAll = newValue;
|
||||||
|
for (let table of nodeTableList) {
|
||||||
|
let newData = table.data;
|
||||||
|
for (let i = 0; i < newData.length; i++) {
|
||||||
|
if (newValue) {
|
||||||
|
// if IO affinity mask for all is checked, then uncheck the individual processors
|
||||||
|
newData[i][AffinityType.IOAffinity] = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
await this.setTableData(table, newData);
|
||||||
|
this.resetNumaNodes();
|
||||||
|
}
|
||||||
|
}, this.objectInfo.autoProcessorAffinityIOMaskForAll, isEnabled);
|
||||||
|
|
||||||
|
this.processorsSection = this.createGroup('', [
|
||||||
|
this.autoSetProcessorAffinityMaskForAllCheckbox,
|
||||||
|
this.autoSetProcessorIOAffinityMaskForAllCheckbox,
|
||||||
|
], false);
|
||||||
|
|
||||||
|
this.processorsSection.addItems(tableGroups);
|
||||||
|
this.processorsTab = this.createTab(this.processorsTabId, localizedConstants.ProcessorsText, this.processorsSection);
|
||||||
|
}
|
||||||
|
|
||||||
|
private createProcessorTable(numaNode: NumaNode): azdata.TableComponent {
|
||||||
|
const cssClass = 'no-borders';
|
||||||
|
let tableData = numaNode.processors.map(row => [localizedConstants.serverCPULabel(row.processorId), row.affinity, row.ioAffinity]);
|
||||||
|
let processorTable = this.createTable(localizedConstants.processorLabel,
|
||||||
|
[
|
||||||
|
<azdata.TableColumn>{
|
||||||
|
name: localizedConstants.processorColumnText,
|
||||||
|
value: localizedConstants.processorColumnText,
|
||||||
|
type: azdata.ColumnType.text,
|
||||||
|
cssClass: cssClass,
|
||||||
|
headerCssClass: cssClass,
|
||||||
|
},
|
||||||
|
<azdata.TableColumn>{
|
||||||
|
name: localizedConstants.processorAffinityColumnText,
|
||||||
|
value: localizedConstants.processorAffinityColumnText,
|
||||||
|
type: azdata.ColumnType.checkBox,
|
||||||
|
width: DefaultColumnCheckboxWidth,
|
||||||
|
action: azdata.ActionOnCellCheckboxCheck.customAction,
|
||||||
|
cssClass: cssClass,
|
||||||
|
headerCssClass: cssClass,
|
||||||
|
},
|
||||||
|
<azdata.TableColumn>{
|
||||||
|
name: localizedConstants.processorIOAffinityColumnText,
|
||||||
|
value: localizedConstants.processorIOAffinityColumnText,
|
||||||
|
type: azdata.ColumnType.checkBox,
|
||||||
|
width: DefaultColumnCheckboxWidth,
|
||||||
|
action: azdata.ActionOnCellCheckboxCheck.customAction,
|
||||||
|
cssClass: cssClass,
|
||||||
|
headerCssClass: cssClass,
|
||||||
|
}
|
||||||
|
], tableData);
|
||||||
|
|
||||||
|
this.disposables.push(processorTable.onCellAction(async (row) => {
|
||||||
|
if (processorTable.selectedRows.length > 0) {
|
||||||
|
const result = processorTable.data;
|
||||||
|
let checkboxState = <azdata.ICheckboxCellActionEventArgs>row;
|
||||||
|
let columnToAdjust = checkboxState.column === AffinityType.ProcessorAffinity ? AffinityType.IOAffinity : AffinityType.ProcessorAffinity;
|
||||||
|
if (result[checkboxState.row][columnToAdjust]) {
|
||||||
|
result[checkboxState.row][columnToAdjust] = !checkboxState.checked;
|
||||||
|
processorTable.updateCells = result[checkboxState.row];
|
||||||
|
}
|
||||||
|
// uncheck the set all processors checkbox
|
||||||
|
if (checkboxState.column === AffinityType.ProcessorAffinity) {
|
||||||
|
this.autoSetProcessorAffinityMaskForAllCheckbox.checked = false;
|
||||||
|
this.objectInfo.autoProcessorAffinityMaskForAll = false;
|
||||||
|
this.objectInfo.numaNodes[+numaNode.numaNodeId].processors[checkboxState.row].affinity = checkboxState.checked;
|
||||||
|
this.objectInfo.numaNodes[+numaNode.numaNodeId].processors[checkboxState.row].ioAffinity = false;
|
||||||
|
}
|
||||||
|
if (checkboxState.column === AffinityType.IOAffinity) {
|
||||||
|
this.autoSetProcessorIOAffinityMaskForAllCheckbox.checked = false;
|
||||||
|
this.objectInfo.autoProcessorAffinityIOMaskForAll = false;
|
||||||
|
this.objectInfo.numaNodes[+numaNode.numaNodeId].processors[checkboxState.row].ioAffinity = checkboxState.checked;
|
||||||
|
this.objectInfo.numaNodes[+numaNode.numaNodeId].processors[checkboxState.row].affinity = false;
|
||||||
|
}
|
||||||
|
this.onFormFieldChange();
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
return processorTable;
|
||||||
|
}
|
||||||
|
|
||||||
|
private resetNumaNodes(): void {
|
||||||
|
for (let node of this.objectInfo.numaNodes) {
|
||||||
|
for (let cpu of node.processors) {
|
||||||
|
cpu.ioAffinity = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import * as uiLoc from '../ui/localizedConstants';
|
|||||||
|
|
||||||
export const DefaultLabelWidth = 150;
|
export const DefaultLabelWidth = 150;
|
||||||
export const DefaultInputWidth = 300;
|
export const DefaultInputWidth = 300;
|
||||||
|
export const DefaultColumnCheckboxWidth = 150;
|
||||||
export const DefaultTableWidth = DefaultInputWidth + DefaultLabelWidth;
|
export const DefaultTableWidth = DefaultInputWidth + DefaultLabelWidth;
|
||||||
export const DefaultMaxTableRowCount = 10;
|
export const DefaultMaxTableRowCount = 10;
|
||||||
export const DefaultMinTableRowCount = 1;
|
export const DefaultMinTableRowCount = 1;
|
||||||
@@ -255,7 +256,7 @@ export abstract class DialogBase<DialogResult> {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
protected createTable(ariaLabel: string, columns: string[], data: any[][], maxRowCount: number = DefaultMaxTableRowCount): azdata.TableComponent {
|
protected createTable(ariaLabel: string, columns: string[] | azdata.TableColumn[], data: any[][], maxRowCount: number = DefaultMaxTableRowCount): azdata.TableComponent {
|
||||||
const table = this.modelView.modelBuilder.table().withProps(
|
const table = this.modelView.modelBuilder.table().withProps(
|
||||||
{
|
{
|
||||||
ariaLabel: ariaLabel,
|
ariaLabel: ariaLabel,
|
||||||
|
|||||||
Reference in New Issue
Block a user