mirror of
https://github.com/ckaczor/sqltoolsservice.git
synced 2026-02-16 10:58:30 -05:00
Switch back to event from locks to fix blocking issues. (#111)
This commit is contained in:
@@ -15,7 +15,7 @@ namespace Microsoft.SqlTools.ServiceLayer.LanguageServices
|
||||
/// Main class for the Binding Queue
|
||||
/// </summary>
|
||||
public class BindingQueue<T> where T : IBindingContext, new()
|
||||
{
|
||||
{
|
||||
private CancellationTokenSource processQueueCancelToken = new CancellationTokenSource();
|
||||
|
||||
private ManualResetEvent itemQueuedEvent = new ManualResetEvent(initialState: false);
|
||||
@@ -197,14 +197,18 @@ namespace Microsoft.SqlTools.ServiceLayer.LanguageServices
|
||||
// prefer the queue item binding item, otherwise use the context default timeout
|
||||
int bindTimeout = queueItem.BindingTimeout ?? bindingContext.BindingTimeout;
|
||||
|
||||
// handle the case a previous binding operation is still running
|
||||
if (!Monitor.TryEnter(bindingContext.BindingLock, bindTimeout))
|
||||
// handle the case a previous binding operation is still running
|
||||
if (!bindingContext.BindingLock.WaitOne(0))
|
||||
{
|
||||
queueItem.Result = queueItem.TimeoutOperation(bindingContext);
|
||||
queueItem.ItemProcessed.Set();
|
||||
queueItem.Result = queueItem.TimeoutOperation != null
|
||||
? queueItem.TimeoutOperation(bindingContext)
|
||||
: null;
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
bindingContext.BindingLock.Reset();
|
||||
|
||||
lockTaken = true;
|
||||
|
||||
// execute the binding operation
|
||||
@@ -231,9 +235,10 @@ namespace Microsoft.SqlTools.ServiceLayer.LanguageServices
|
||||
{
|
||||
queueItem.Result = queueItem.TimeoutOperation(bindingContext);
|
||||
}
|
||||
|
||||
lockTaken = false;
|
||||
|
||||
// we'll need to wait for the task to finsh canceling otherwise future binding will fail
|
||||
bindTask.Wait();
|
||||
bindTask.ContinueWith((a) => bindingContext.BindingLock.Set());
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
@@ -246,7 +251,7 @@ namespace Microsoft.SqlTools.ServiceLayer.LanguageServices
|
||||
{
|
||||
if (lockTaken)
|
||||
{
|
||||
Monitor.Exit(bindingContext.BindingLock);
|
||||
bindingContext.BindingLock.Set();
|
||||
}
|
||||
|
||||
queueItem.ItemProcessed.Set();
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
//
|
||||
|
||||
using System;
|
||||
using System.Threading;
|
||||
using Microsoft.SqlServer.Management.Common;
|
||||
using Microsoft.SqlServer.Management.SmoMetadataProvider;
|
||||
using Microsoft.SqlServer.Management.SqlParser.Binder;
|
||||
@@ -20,7 +21,7 @@ namespace Microsoft.SqlTools.ServiceLayer.LanguageServices
|
||||
{
|
||||
private ParseOptions parseOptions;
|
||||
|
||||
private object bindingLock;
|
||||
private ManualResetEvent bindingLock;
|
||||
|
||||
private ServerConnection serverConnection;
|
||||
|
||||
@@ -29,7 +30,7 @@ namespace Microsoft.SqlTools.ServiceLayer.LanguageServices
|
||||
/// </summary>
|
||||
public ConnectedBindingContext()
|
||||
{
|
||||
this.bindingLock = new object();
|
||||
this.bindingLock = new ManualResetEvent(initialState: true);
|
||||
this.BindingTimeout = ConnectedBindingQueue.DefaultBindingTimeout;
|
||||
this.MetadataDisplayInfoProvider = new MetadataDisplayInfoProvider();
|
||||
}
|
||||
@@ -75,7 +76,7 @@ namespace Microsoft.SqlTools.ServiceLayer.LanguageServices
|
||||
/// <summary>
|
||||
/// Gets the binding lock object
|
||||
/// </summary>
|
||||
public object BindingLock
|
||||
public ManualResetEvent BindingLock
|
||||
{
|
||||
get
|
||||
{
|
||||
|
||||
@@ -21,7 +21,7 @@ namespace Microsoft.SqlTools.ServiceLayer.LanguageServices
|
||||
/// </summary>
|
||||
public class ConnectedBindingQueue : BindingQueue<ConnectedBindingContext>
|
||||
{
|
||||
internal const int DefaultBindingTimeout = 60000;
|
||||
internal const int DefaultBindingTimeout = 500;
|
||||
|
||||
internal const int DefaultMinimumConnectionTimeout = 30;
|
||||
|
||||
@@ -63,10 +63,12 @@ namespace Microsoft.SqlTools.ServiceLayer.LanguageServices
|
||||
string connectionKey = GetConnectionContextKey(connInfo);
|
||||
IBindingContext bindingContext = this.GetOrCreateBindingContext(connectionKey);
|
||||
|
||||
lock (bindingContext.BindingLock)
|
||||
if (bindingContext.BindingLock.WaitOne())
|
||||
{
|
||||
try
|
||||
{
|
||||
bindingContext.BindingLock.Reset();
|
||||
|
||||
// increase the connection timeout to at least 30 seconds and and build connection string
|
||||
// enable PersistSecurityInfo to handle issues in SMO where the connection context is lost in reconnections
|
||||
int? originalTimeout = connInfo.ConnectionDetails.ConnectTimeout;
|
||||
@@ -96,7 +98,11 @@ namespace Microsoft.SqlTools.ServiceLayer.LanguageServices
|
||||
catch (Exception)
|
||||
{
|
||||
bindingContext.IsConnected = false;
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
bindingContext.BindingLock.Set();
|
||||
}
|
||||
}
|
||||
|
||||
return connectionKey;
|
||||
|
||||
@@ -46,7 +46,7 @@ namespace Microsoft.SqlTools.ServiceLayer.LanguageServices
|
||||
/// <summary>
|
||||
/// Gets the binding lock object
|
||||
/// </summary>
|
||||
object BindingLock { get; }
|
||||
ManualResetEvent BindingLock { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the binding operation timeout in milliseconds
|
||||
|
||||
@@ -37,11 +37,9 @@ namespace Microsoft.SqlTools.ServiceLayer.LanguageServices
|
||||
|
||||
internal const int DiagnosticParseDelay = 750;
|
||||
|
||||
internal const int HoverTimeout = 3000;
|
||||
internal const int HoverTimeout = 500;
|
||||
|
||||
internal const int BindingTimeout = 3000;
|
||||
|
||||
internal const int FindCompletionStartTimeout = 50;
|
||||
internal const int BindingTimeout = 500;
|
||||
|
||||
internal const int OnConnectionWaitTimeout = 300000;
|
||||
|
||||
@@ -252,7 +250,7 @@ namespace Microsoft.SqlTools.ServiceLayer.LanguageServices
|
||||
await Task.FromResult(true);
|
||||
}
|
||||
else
|
||||
{
|
||||
{
|
||||
// get the current list of completion items and return to client
|
||||
var scriptFile = LanguageService.WorkspaceServiceInstance.Workspace.GetFile(
|
||||
textDocumentPosition.TextDocument.Uri);
|
||||
@@ -628,7 +626,7 @@ namespace Microsoft.SqlTools.ServiceLayer.LanguageServices
|
||||
ScriptParseInfo scriptParseInfo = GetScriptParseInfo(textDocumentPosition.TextDocument.Uri);
|
||||
if (scriptParseInfo != null && scriptParseInfo.ParseResult != null)
|
||||
{
|
||||
if (Monitor.TryEnter(scriptParseInfo.BuildingMetadataLock, LanguageService.FindCompletionStartTimeout))
|
||||
if (Monitor.TryEnter(scriptParseInfo.BuildingMetadataLock))
|
||||
{
|
||||
try
|
||||
{
|
||||
@@ -711,8 +709,7 @@ namespace Microsoft.SqlTools.ServiceLayer.LanguageServices
|
||||
}
|
||||
Token token = GetToken(scriptParseInfo, line, column);
|
||||
|
||||
if (scriptParseInfo.IsConnected
|
||||
&& Monitor.TryEnter(scriptParseInfo.BuildingMetadataLock, LanguageService.FindCompletionStartTimeout))
|
||||
if (scriptParseInfo.IsConnected && Monitor.TryEnter(scriptParseInfo.BuildingMetadataLock))
|
||||
{
|
||||
try
|
||||
{
|
||||
|
||||
@@ -24,7 +24,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Test.LanguageServices
|
||||
{
|
||||
public TestBindingContext()
|
||||
{
|
||||
this.BindingLock = new object();
|
||||
this.BindingLock = new ManualResetEvent(true);
|
||||
this.BindingTimeout = 3000;
|
||||
}
|
||||
|
||||
@@ -38,7 +38,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Test.LanguageServices
|
||||
|
||||
public IBinder Binder { get; set; }
|
||||
|
||||
public object BindingLock { get; set; }
|
||||
public ManualResetEvent BindingLock { get; set; }
|
||||
|
||||
public int BindingTimeout { get; set; }
|
||||
|
||||
|
||||
Reference in New Issue
Block a user