mirror of
https://github.com/ckaczor/sqltoolsservice.git
synced 2026-01-27 01:25:42 -05:00
Move unused forked code to external directory (#1192)
* Move unused forked code to external directory * Fix SLN build errors * Add back resource provider core since it's referenced by main resource provider project * Update PackageProjects step of pipeline
This commit is contained in:
453
external/Microsoft.SqlTools.CoreServices/Connection/ReliableConnection/AmbientSettings.cs
vendored
Normal file
453
external/Microsoft.SqlTools.CoreServices/Connection/ReliableConnection/AmbientSettings.cs
vendored
Normal file
@@ -0,0 +1,453 @@
|
||||
//
|
||||
// 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.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Reflection;
|
||||
using Microsoft.SqlTools.Hosting.Utility;
|
||||
|
||||
namespace Microsoft.SqlTools.CoreServices.Connection.ReliableConnection
|
||||
{
|
||||
/// <summary>
|
||||
/// This class represents connection (and other) settings specified by called of the DacFx API. DacFx
|
||||
/// cannot rely on the registry to supply override values therefore setting overrides must be made
|
||||
/// by the top-of-the-stack
|
||||
/// </summary>
|
||||
internal sealed class AmbientSettings
|
||||
{
|
||||
private const string LogicalContextName = "__LocalContextConfigurationName";
|
||||
|
||||
internal enum StreamBackingStore
|
||||
{
|
||||
// MemoryStream
|
||||
Memory = 0,
|
||||
|
||||
// FileStream
|
||||
File = 1
|
||||
}
|
||||
|
||||
// Internal for test purposes
|
||||
internal const string MasterReferenceFilePathIndex = "MasterReferenceFilePath";
|
||||
internal const string DatabaseLockTimeoutIndex = "DatabaseLockTimeout";
|
||||
internal const string QueryTimeoutIndex = "QueryTimeout";
|
||||
internal const string LongRunningQueryTimeoutIndex = "LongRunningQueryTimeout";
|
||||
internal const string AlwaysRetryOnTransientFailureIndex = "AlwaysRetryOnTransientFailure";
|
||||
internal const string MaxDataReaderDegreeOfParallelismIndex = "MaxDataReaderDegreeOfParallelism";
|
||||
internal const string ConnectionRetryHandlerIndex = "ConnectionRetryHandler";
|
||||
internal const string TraceRowCountFailureIndex = "TraceRowCountFailure";
|
||||
internal const string TableProgressUpdateIntervalIndex = "TableProgressUpdateInterval";
|
||||
internal const string UseOfflineDataReaderIndex = "UseOfflineDataReader";
|
||||
internal const string StreamBackingStoreForOfflineDataReadingIndex = "StreamBackingStoreForOfflineDataReading";
|
||||
internal const string DisableIndexesForDataPhaseIndex = "DisableIndexesForDataPhase";
|
||||
internal const string ReliableDdlEnabledIndex = "ReliableDdlEnabled";
|
||||
internal const string ImportModelDatabaseIndex = "ImportModelDatabase";
|
||||
internal const string SupportAlwaysEncryptedIndex = "SupportAlwaysEncrypted";
|
||||
internal const string SkipObjectTypeBlockingIndex = "SkipObjectTypeBlocking";
|
||||
internal const string DoNotSerializeQueryStoreSettingsIndex = "DoNotSerializeQueryStoreSettings";
|
||||
internal const string AlwaysEncryptedWizardMigrationIndex = "AlwaysEncryptedWizardMigration";
|
||||
|
||||
internal static AmbientData _defaultSettings;
|
||||
|
||||
static AmbientSettings()
|
||||
{
|
||||
_defaultSettings = new AmbientData();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Access to the default ambient settings. Access to these settings is made available
|
||||
/// for SSDT scenarios where settings are read from the registry and not set explicitly through
|
||||
/// the API
|
||||
/// </summary>
|
||||
public static AmbientData DefaultSettings
|
||||
{
|
||||
get { return _defaultSettings; }
|
||||
}
|
||||
|
||||
public static string MasterReferenceFilePath
|
||||
{
|
||||
get { return GetValue<string>(MasterReferenceFilePathIndex); }
|
||||
}
|
||||
|
||||
public static int LockTimeoutMilliSeconds
|
||||
{
|
||||
get { return GetValue<int>(DatabaseLockTimeoutIndex); }
|
||||
}
|
||||
|
||||
public static int QueryTimeoutSeconds
|
||||
{
|
||||
get { return GetValue<int>(QueryTimeoutIndex); }
|
||||
}
|
||||
|
||||
public static int LongRunningQueryTimeoutSeconds
|
||||
{
|
||||
get { return GetValue<int>(LongRunningQueryTimeoutIndex); }
|
||||
}
|
||||
|
||||
public static Action<SqlServerRetryError> ConnectionRetryMessageHandler
|
||||
{
|
||||
get { return GetValue<Action<SqlServerRetryError>>(ConnectionRetryHandlerIndex); }
|
||||
}
|
||||
|
||||
public static bool AlwaysRetryOnTransientFailure
|
||||
{
|
||||
get { return GetValue<bool>(AlwaysRetryOnTransientFailureIndex); }
|
||||
}
|
||||
|
||||
public static int MaxDataReaderDegreeOfParallelism
|
||||
{
|
||||
get { return GetValue<int>(MaxDataReaderDegreeOfParallelismIndex); }
|
||||
}
|
||||
|
||||
public static int TableProgressUpdateInterval
|
||||
{
|
||||
// value of zero means do not fire 'heartbeat' progress events. Non-zero values will
|
||||
// fire a heartbeat progress event every n seconds.
|
||||
get { return GetValue<int>(TableProgressUpdateIntervalIndex); }
|
||||
}
|
||||
|
||||
public static bool TraceRowCountFailure
|
||||
{
|
||||
get { return GetValue<bool>(TraceRowCountFailureIndex); }
|
||||
}
|
||||
|
||||
public static bool UseOfflineDataReader
|
||||
{
|
||||
get { return GetValue<bool>(UseOfflineDataReaderIndex); }
|
||||
}
|
||||
|
||||
public static StreamBackingStore StreamBackingStoreForOfflineDataReading
|
||||
{
|
||||
get { return GetValue<StreamBackingStore>(StreamBackingStoreForOfflineDataReadingIndex); }
|
||||
}
|
||||
|
||||
public static bool DisableIndexesForDataPhase
|
||||
{
|
||||
get { return GetValue<bool>(DisableIndexesForDataPhaseIndex); }
|
||||
}
|
||||
|
||||
public static bool ReliableDdlEnabled
|
||||
{
|
||||
get { return GetValue<bool>(ReliableDdlEnabledIndex); }
|
||||
}
|
||||
|
||||
public static bool ImportModelDatabase
|
||||
{
|
||||
get { return GetValue<bool>(ImportModelDatabaseIndex); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Setting that shows whether Always Encrypted is supported.
|
||||
/// If false, then reverse engineering and script interpretation of a database with any Always Encrypted object will fail
|
||||
/// </summary>
|
||||
public static bool SupportAlwaysEncrypted
|
||||
{
|
||||
get { return GetValue<bool>(SupportAlwaysEncryptedIndex); }
|
||||
}
|
||||
|
||||
public static bool AlwaysEncryptedWizardMigration
|
||||
{
|
||||
get { return GetValue<bool>(AlwaysEncryptedWizardMigrationIndex); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Setting that determines whether checks for unsupported object types are performed.
|
||||
/// If false, unsupported object types will prevent extract from being performed.
|
||||
/// Default value is false.
|
||||
/// </summary>
|
||||
public static bool SkipObjectTypeBlocking
|
||||
{
|
||||
get { return GetValue<bool>(SkipObjectTypeBlockingIndex); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Setting that determines whether the Database Options that store Query Store settings will be left out during package serialization.
|
||||
/// Default value is false.
|
||||
/// </summary>
|
||||
public static bool DoNotSerializeQueryStoreSettings
|
||||
{
|
||||
get { return GetValue<bool>(DoNotSerializeQueryStoreSettingsIndex); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called by top-of-stack API to setup/configure settings that should be used
|
||||
/// throughout the API (lower in the stack). The settings are reverted once the returned context
|
||||
/// has been disposed.
|
||||
/// </summary>
|
||||
public static IStackSettingsContext CreateSettingsContext()
|
||||
{
|
||||
return new StackConfiguration();
|
||||
}
|
||||
|
||||
private static T1 GetValue<T1>(string configIndex)
|
||||
{
|
||||
IAmbientDataDirectAccess config = _defaultSettings;
|
||||
|
||||
return (T1)config.Data[configIndex].Value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Data-transfer object that represents a specific configuration
|
||||
/// </summary>
|
||||
public class AmbientData : IAmbientDataDirectAccess
|
||||
{
|
||||
private readonly Dictionary<string, AmbientValue> _configuration;
|
||||
|
||||
public AmbientData()
|
||||
{
|
||||
_configuration = new Dictionary<string, AmbientValue>(StringComparer.OrdinalIgnoreCase);
|
||||
_configuration[DatabaseLockTimeoutIndex] = new AmbientValue(5000);
|
||||
_configuration[QueryTimeoutIndex] = new AmbientValue(60);
|
||||
_configuration[LongRunningQueryTimeoutIndex] = new AmbientValue(0);
|
||||
_configuration[AlwaysRetryOnTransientFailureIndex] = new AmbientValue(false);
|
||||
_configuration[ConnectionRetryHandlerIndex] = new AmbientValue(typeof(Action<SqlServerRetryError>), null);
|
||||
_configuration[MaxDataReaderDegreeOfParallelismIndex] = new AmbientValue(8);
|
||||
_configuration[TraceRowCountFailureIndex] = new AmbientValue(false); // default: throw DacException on rowcount mismatch during import/export data validation
|
||||
_configuration[TableProgressUpdateIntervalIndex] = new AmbientValue(300); // default: fire heartbeat progress update events every 5 minutes
|
||||
_configuration[UseOfflineDataReaderIndex] = new AmbientValue(false);
|
||||
_configuration[StreamBackingStoreForOfflineDataReadingIndex] = new AmbientValue(StreamBackingStore.File); //applicable only when UseOfflineDataReader is set to true
|
||||
_configuration[MasterReferenceFilePathIndex] = new AmbientValue(typeof(string), null);
|
||||
// Defect 1210884: Enable an option to allow secondary index, check and fk constraints to stay enabled during data upload with import in DACFX for IES
|
||||
_configuration[DisableIndexesForDataPhaseIndex] = new AmbientValue(true);
|
||||
_configuration[ReliableDdlEnabledIndex] = new AmbientValue(false);
|
||||
_configuration[ImportModelDatabaseIndex] = new AmbientValue(true);
|
||||
_configuration[SupportAlwaysEncryptedIndex] = new AmbientValue(false);
|
||||
_configuration[AlwaysEncryptedWizardMigrationIndex] = new AmbientValue(false);
|
||||
_configuration[SkipObjectTypeBlockingIndex] = new AmbientValue(false);
|
||||
_configuration[DoNotSerializeQueryStoreSettingsIndex] = new AmbientValue(false);
|
||||
}
|
||||
|
||||
public string MasterReferenceFilePath
|
||||
{
|
||||
get { return (string)_configuration[MasterReferenceFilePathIndex].Value; }
|
||||
set { _configuration[MasterReferenceFilePathIndex].Value = value; }
|
||||
}
|
||||
|
||||
public int LockTimeoutMilliSeconds
|
||||
{
|
||||
get { return (int)_configuration[DatabaseLockTimeoutIndex].Value; }
|
||||
set { _configuration[DatabaseLockTimeoutIndex].Value = value; }
|
||||
}
|
||||
public int QueryTimeoutSeconds
|
||||
{
|
||||
get { return (int)_configuration[QueryTimeoutIndex].Value; }
|
||||
set { _configuration[QueryTimeoutIndex].Value = value; }
|
||||
}
|
||||
public int LongRunningQueryTimeoutSeconds
|
||||
{
|
||||
get { return (int)_configuration[LongRunningQueryTimeoutIndex].Value; }
|
||||
set { _configuration[LongRunningQueryTimeoutIndex].Value = value; }
|
||||
}
|
||||
public bool AlwaysRetryOnTransientFailure
|
||||
{
|
||||
get { return (bool)_configuration[AlwaysRetryOnTransientFailureIndex].Value; }
|
||||
set { _configuration[AlwaysRetryOnTransientFailureIndex].Value = value; }
|
||||
}
|
||||
public Action<SqlServerRetryError> ConnectionRetryMessageHandler
|
||||
{
|
||||
get { return (Action<SqlServerRetryError>)_configuration[ConnectionRetryHandlerIndex].Value; }
|
||||
set { _configuration[ConnectionRetryHandlerIndex].Value = value; }
|
||||
}
|
||||
public bool TraceRowCountFailure
|
||||
{
|
||||
get { return (bool)_configuration[TraceRowCountFailureIndex].Value; }
|
||||
set { _configuration[TraceRowCountFailureIndex].Value = value; }
|
||||
}
|
||||
public int TableProgressUpdateInterval
|
||||
{
|
||||
get { return (int)_configuration[TableProgressUpdateIntervalIndex].Value; }
|
||||
set { _configuration[TableProgressUpdateIntervalIndex].Value = value; }
|
||||
}
|
||||
|
||||
public bool UseOfflineDataReader
|
||||
{
|
||||
get { return (bool)_configuration[UseOfflineDataReaderIndex].Value; }
|
||||
set { _configuration[UseOfflineDataReaderIndex].Value = value; }
|
||||
}
|
||||
|
||||
public StreamBackingStore StreamBackingStoreForOfflineDataReading
|
||||
{
|
||||
get { return (StreamBackingStore)_configuration[StreamBackingStoreForOfflineDataReadingIndex].Value; }
|
||||
set { _configuration[StreamBackingStoreForOfflineDataReadingIndex].Value = value; }
|
||||
}
|
||||
|
||||
public bool DisableIndexesForDataPhase
|
||||
{
|
||||
get { return (bool)_configuration[DisableIndexesForDataPhaseIndex].Value; }
|
||||
set { _configuration[DisableIndexesForDataPhaseIndex].Value = value; }
|
||||
}
|
||||
|
||||
public bool ReliableDdlEnabled
|
||||
{
|
||||
get { return (bool)_configuration[ReliableDdlEnabledIndex].Value; }
|
||||
set { _configuration[ReliableDdlEnabledIndex].Value = value; }
|
||||
}
|
||||
|
||||
public bool ImportModelDatabase
|
||||
{
|
||||
get { return (bool)_configuration[ImportModelDatabaseIndex].Value; }
|
||||
set { _configuration[ImportModelDatabaseIndex].Value = value; }
|
||||
}
|
||||
|
||||
internal bool SupportAlwaysEncrypted
|
||||
{
|
||||
get { return (bool)_configuration[SupportAlwaysEncryptedIndex].Value; }
|
||||
set { _configuration[SupportAlwaysEncryptedIndex].Value = value; }
|
||||
}
|
||||
|
||||
internal bool AlwaysEncryptedWizardMigration
|
||||
{
|
||||
get { return (bool)_configuration[AlwaysEncryptedWizardMigrationIndex].Value; }
|
||||
set { _configuration[AlwaysEncryptedWizardMigrationIndex].Value = value; }
|
||||
}
|
||||
|
||||
internal bool SkipObjectTypeBlocking
|
||||
{
|
||||
get { return (bool)_configuration[SkipObjectTypeBlockingIndex].Value; }
|
||||
set { _configuration[SkipObjectTypeBlockingIndex].Value = value; }
|
||||
}
|
||||
|
||||
internal bool DoNotSerializeQueryStoreSettings
|
||||
{
|
||||
get { return (bool)_configuration[DoNotSerializeQueryStoreSettingsIndex].Value; }
|
||||
set { _configuration[DoNotSerializeQueryStoreSettingsIndex].Value = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Provides a way to bulk populate settings from a dictionary
|
||||
/// </summary>
|
||||
public void PopulateSettings(IDictionary<string, object> settingsCollection)
|
||||
{
|
||||
if (settingsCollection != null)
|
||||
{
|
||||
Dictionary<string, object> newSettings = new Dictionary<string, object>();
|
||||
|
||||
// We know all the values are set on the current configuration
|
||||
foreach (KeyValuePair<string, object> potentialPair in settingsCollection)
|
||||
{
|
||||
AmbientValue currentValue;
|
||||
if (_configuration.TryGetValue(potentialPair.Key, out currentValue))
|
||||
{
|
||||
object newValue = potentialPair.Value;
|
||||
newSettings[potentialPair.Key] = newValue;
|
||||
}
|
||||
}
|
||||
|
||||
if (newSettings.Count > 0)
|
||||
{
|
||||
foreach (KeyValuePair<string, object> newSetting in newSettings)
|
||||
{
|
||||
_configuration[newSetting.Key].Value = newSetting.Value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Logs the Ambient Settings
|
||||
/// </summary>
|
||||
public void TraceSettings()
|
||||
{
|
||||
// NOTE: logging as warning so we can get this data in the IEService DacFx logs
|
||||
Logger.Write(TraceEventType.Warning, Resources.LoggingAmbientSettings);
|
||||
|
||||
foreach (KeyValuePair<string, AmbientValue> setting in _configuration)
|
||||
{
|
||||
// Log Ambient Settings
|
||||
Logger.Write(
|
||||
TraceEventType.Warning,
|
||||
string.Format(
|
||||
Resources.AmbientSettingFormat,
|
||||
setting.Key,
|
||||
setting.Value == null ? setting.Value : setting.Value.Value));
|
||||
}
|
||||
}
|
||||
|
||||
Dictionary<string, AmbientValue> IAmbientDataDirectAccess.Data
|
||||
{
|
||||
get { return _configuration; }
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This class is used as value in the dictionary to ensure that the type of value is correct.
|
||||
/// </summary>
|
||||
private class AmbientValue
|
||||
{
|
||||
private readonly Type _type;
|
||||
private readonly bool _isTypeNullable;
|
||||
private object _value;
|
||||
|
||||
public AmbientValue(object value)
|
||||
: this(value == null ? null : value.GetType(), value)
|
||||
{
|
||||
}
|
||||
|
||||
public AmbientValue(Type type, object value)
|
||||
{
|
||||
if (type == null)
|
||||
{
|
||||
throw new ArgumentNullException("type");
|
||||
}
|
||||
_type = type;
|
||||
_isTypeNullable = !type.GetTypeInfo().IsValueType || Nullable.GetUnderlyingType(type) != null;
|
||||
Value = value;
|
||||
}
|
||||
|
||||
public object Value
|
||||
{
|
||||
get { return _value; }
|
||||
set
|
||||
{
|
||||
if ((_isTypeNullable && value == null) || _type.GetTypeInfo().IsInstanceOfType(value))
|
||||
{
|
||||
_value = value;
|
||||
}
|
||||
else
|
||||
{
|
||||
Logger.Write(TraceEventType.Error, string.Format(Resources.UnableToAssignValue, value.GetType().FullName, _type.FullName));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This private interface allows pass-through access directly to member data
|
||||
/// </summary>
|
||||
private interface IAmbientDataDirectAccess
|
||||
{
|
||||
Dictionary<string, AmbientValue> Data { get; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This class encapsulated the concept of configuration that is set on the stack and
|
||||
/// flows across multiple threads as part of the logical call context
|
||||
/// </summary>
|
||||
private sealed class StackConfiguration : IStackSettingsContext
|
||||
{
|
||||
private readonly AmbientData _data;
|
||||
|
||||
public StackConfiguration()
|
||||
{
|
||||
_data = new AmbientData();
|
||||
//CallContext.LogicalSetData(LogicalContextName, _data);
|
||||
}
|
||||
|
||||
public AmbientData Settings
|
||||
{
|
||||
get { return _data; }
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Dispose(true);
|
||||
}
|
||||
private void Dispose(bool disposing)
|
||||
{
|
||||
//CallContext.LogicalSetData(LogicalContextName, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user