// // Copyright (c) Microsoft. All rights reserved. // Licensed under the MIT license. See LICENSE file in the project root for full license information. // using Microsoft.SqlServer.Management.Common; using Microsoft.SqlServer.Management.Smo; using Microsoft.SqlTools.Hosting.Protocol; using Microsoft.SqlTools.ServiceLayer.Connection; using Microsoft.SqlTools.ServiceLayer.Hosting; using Microsoft.SqlTools.ServiceLayer.ServerConfigurations.Contracts; using Microsoft.SqlTools.Utility; using System; using System.Collections.Generic; using System.Diagnostics; using System.Threading.Tasks; namespace Microsoft.SqlTools.ServiceLayer.ServerConfigurations { public class ServerConfigService { private ConnectionService connectionService = null; private static readonly Lazy instance = new Lazy(() => new ServerConfigService()); /// /// Gets the singleton instance object /// public static ServerConfigService Instance { get { return instance.Value; } } /// /// Internal for testing purposes only /// internal ConnectionService ConnectionServiceInstance { get { if (connectionService == null) { connectionService = ConnectionService.Instance; } return connectionService; } set { connectionService = value; } } public void InitializeService(ServiceHost serviceHost) { serviceHost.SetRequestHandler(ServerConfigViewRequest.Type, this.HandleServerConfigViewRequest); serviceHost.SetRequestHandler(ServerConfigUpdateRequest.Type, this.HandleServerConfigUpdateRequest); serviceHost.SetRequestHandler(ServerConfigListRequest.Type, this.HandleServerConfigListRequest); } /// /// Handles config view request /// /// Request parameters /// Request Context /// public async Task HandleServerConfigViewRequest(ServerConfigViewRequestParams parameters, RequestContext requestContext) { Logger.Write(TraceEventType.Verbose, "HandleServerConfigViewRequest"); try { ConnectionInfo connInfo; ConnectionServiceInstance.TryFindConnection( parameters.OwnerUri, out connInfo); if (connInfo == null) { await requestContext.SendError(new Exception(SR.ProfilerConnectionNotFound)); } else { var serverConnection = ConnectionService.OpenServerConnection(connInfo); ServerConfigProperty serverConfig = GetConfig(serverConnection, parameters.ConfigNumber); await requestContext.SendResult(new ServerConfigViewResponseParams { ConfigProperty = serverConfig }); } } catch (Exception e) { // Exception related to run task will be captured here await requestContext.SendError(e); } } /// /// Handles config update request /// /// Request parameters /// Request Context /// public async Task HandleServerConfigUpdateRequest(ServerConfigUpdateRequestParams parameters, RequestContext requestContext) { Logger.Write(TraceEventType.Verbose, "HandleServerConfigUpdateRequest"); try { ConnectionInfo connInfo; ConnectionServiceInstance.TryFindConnection( parameters.OwnerUri, out connInfo); ServerConfigUpdateResponseParams response = new ServerConfigUpdateResponseParams { }; if (connInfo == null) { await requestContext.SendError(new Exception(SR.ProfilerConnectionNotFound)); } else { var serverConnection = ConnectionService.OpenServerConnection(connInfo); UpdateConfig(serverConnection, parameters.ConfigNumber, parameters.ConfigValue); response.ConfigProperty = GetConfig(serverConnection, parameters.ConfigNumber); await requestContext.SendResult(response); } } catch (Exception e) { // Exception related to run task will be captured here await requestContext.SendError(e); } } /// /// Handles config list request /// /// Request parameters /// Request Context public async Task HandleServerConfigListRequest(ServerConfigListRequestParams parameters, RequestContext requestContext) { Logger.Write(TraceEventType.Verbose, "HandleServerConfigListRequest"); try { ConnectionInfo connInfo; ConnectionServiceInstance.TryFindConnection( parameters.OwnerUri, out connInfo); ServerConfigListResponseParams response = new ServerConfigListResponseParams { }; if (connInfo == null) { await requestContext.SendError(new Exception(SR.ProfilerConnectionNotFound)); } else { var serverConnection = ConnectionService.OpenServerConnection(connInfo); response.ConfigProperties = GetConfigs(serverConnection); await requestContext.SendResult(response); } } catch (Exception e) { // Exception related to run task will be captured here await requestContext.SendError(e); } } /// /// Updates external script in a given server. Throws exception if server doesn't support external script /// /// /// public void UpdateConfig(ServerConnection serverConnection, int configNumber, int configValue) { Server server = new Server(serverConnection); ConfigProperty serverConfig = GetSmoConfig(server, configNumber); if (serverConfig != null) { try { serverConfig.ConfigValue = configValue; server.Configuration.Alter(true); } catch (FailedOperationException ex) { throw new ServerConfigException($"Failed to update config. config number: ${configNumber}", ex); } } else { throw new ServerConfigException($"Server doesn't have config. config number: ${configNumber}"); } } /// /// Returns current value of external script config /// /// /// private ServerConfigProperty GetConfig(ServerConnection serverConnection, int configNumber) { Server server = new Server(serverConnection); ConfigProperty serverConfig = GetSmoConfig(server, configNumber); return serverConfig != null ? ServerConfigProperty.ToServerConfigProperty(serverConfig) : null; } private List GetConfigs(ServerConnection serverConnection) { Server server = new Server(serverConnection); List list = new List(); foreach (ConfigProperty serverConfig in server.Configuration.Properties) { list.Add(serverConfig != null ? ServerConfigProperty.ToServerConfigProperty(serverConfig) : null); } return list; } private ConfigProperty GetSmoConfig(Server server, int configNumber) { try { ConfigProperty serverConfig = null; foreach (ConfigProperty configProperty in server.Configuration.Properties) { if (configProperty.Number == configNumber) { serverConfig = configProperty; break; } } return serverConfig; } catch (Exception ex) { throw new ServerConfigException($"Failed to get config. config number: ${configNumber}", ex); } } } }