Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Query: Fixes DllNotFoundException when running on Windows/x64 #3226

Merged
merged 12 commits into from
Jun 1, 2022
23 changes: 18 additions & 5 deletions Microsoft.Azure.Cosmos/src/CosmosClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,14 @@ namespace Microsoft.Azure.Cosmos
using System.Collections.Generic;
using System.Diagnostics;
using System.Net;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using global::Azure.Core;
using Microsoft.Azure.Cosmos.Handlers;
using Microsoft.Azure.Cosmos.Query.Core.Monads;
using Microsoft.Azure.Cosmos.Query.Core.QueryPlan;
using Microsoft.Azure.Cosmos.Telemetry;
using Microsoft.Azure.Cosmos.Tracing;
using Microsoft.Azure.Cosmos.Tracing.TraceData;
Expand Down Expand Up @@ -118,11 +121,21 @@ static CosmosClient()
#endif
HttpConstants.Versions.CurrentVersionUTF8 = Encoding.UTF8.GetBytes(HttpConstants.Versions.CurrentVersion);

// V3 always assumes assemblies exists
// Shall revisit on feedback
// NOTE: Native ServiceInteropWrapper.AssembliesExist has appsettings dependency which are proofed for CTL (native dll entry) scenarios.
// Revert of this depends on handling such in direct assembly
ServiceInteropWrapper.AssembliesExist = new Lazy<bool>(() => true);
ServiceInteropWrapper.AssembliesExist = new Lazy<bool>(() =>
{
// Attemp to create an instance of the ServiceInterop assembly
TryCatch<IntPtr> tryCreateServiceProvider = QueryPartitionProvider.TryCreateServiceProvider("{}");
if (tryCreateServiceProvider.Failed)
{
// Failed, either the DLL is not present or one of its dependencies
return false;
}

// Assembly and dependencies are available
// Release pointer
Marshal.Release(tryCreateServiceProvider.Result);
return true;
});

Microsoft.Azure.Cosmos.Core.Trace.DefaultTrace.InitEventListener();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,11 @@ namespace Microsoft.Azure.Cosmos.Query.Core.QueryPlan
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using Microsoft.Azure.Cosmos.Core.Trace;
using Microsoft.Azure.Cosmos.Query.Core.Exceptions;
using Microsoft.Azure.Cosmos.Query.Core.Monads;
using Microsoft.Azure.Cosmos.Routing;
using Microsoft.Azure.Cosmos.Tracing;
using Newtonsoft.Json;
using PartitionKeyDefinition = Documents.PartitionKeyDefinition;
using PartitionKeyInternal = Documents.Routing.PartitionKeyInternal;
Expand Down Expand Up @@ -280,6 +282,30 @@ internal TryCatch<PartitionedQueryExecutionInfoInternal> TryGetPartitionedQueryE
return TryCatch<PartitionedQueryExecutionInfoInternal>.FromResult(queryInfoInternal);
}

internal static TryCatch<IntPtr> TryCreateServiceProvider(string queryEngineConfiguration)
{
try
{
IntPtr serviceProvider = IntPtr.Zero;
uint errorCode = ServiceInteropWrapper.CreateServiceProvider(
queryEngineConfiguration,
out serviceProvider);
Exception exception = Marshal.GetExceptionForHR((int)errorCode);
if (exception != null)
{
DefaultTrace.TraceWarning("QueryPartitionProvider.TryCreateServiceProvider failed with exception {0}", exception);
return TryCatch<IntPtr>.FromException(exception);
}

return TryCatch<IntPtr>.FromResult(serviceProvider);
}
catch (Exception ex)
{
DefaultTrace.TraceWarning("QueryPartitionProvider.TryCreateServiceProvider failed with exception {0}", ex);
return TryCatch<IntPtr>.FromException(ex);
}
}

~QueryPartitionProvider()
{
this.Dispose(false);
Expand All @@ -295,12 +321,13 @@ private void Initialize()
{
if (!this.disposed && this.serviceProvider == IntPtr.Zero)
{
uint errorCode = ServiceInteropWrapper.CreateServiceProvider(
this.queryengineConfiguration,
out this.serviceProvider);
TryCatch<IntPtr> tryCreateServiceProvider = QueryPartitionProvider.TryCreateServiceProvider(this.queryengineConfiguration);
if (tryCreateServiceProvider.Failed)
{
throw ExceptionWithStackTraceException.UnWrapMonadExcepion(tryCreateServiceProvider.Exception, NoOpTrace.Singleton);
}

Exception exception = Marshal.GetExceptionForHR((int)errorCode);
if (exception != null) throw exception;
this.serviceProvider = tryCreateServiceProvider.Result;
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
namespace Microsoft.Azure.Cosmos.Query.Core.QueryPlan
{
using System;
using System.Runtime.InteropServices;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Azure.Cosmos.Query.Core.Monads;
Expand Down Expand Up @@ -116,6 +117,13 @@ public static Task<PartitionedQueryExecutionInfo> GetQueryPlanThroughGatewayAsyn

using (ITrace gatewayQueryPlanTrace = trace.StartChild("Gateway QueryPlan", TraceComponent.Query, TraceLevel.Info))
{
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)
j82w marked this conversation as resolved.
Show resolved Hide resolved
&& Documents.ServiceInteropWrapper.Is64BitProcess)
{
// It's Windows and x64, should have loaded the DLL
gatewayQueryPlanTrace.AddDatum("ServiceInterop unavailable", true);
j82w marked this conversation as resolved.
Show resolved Hide resolved
}

return queryContext.ExecuteQueryPlanRequestAsync(
resourceLink,
ResourceType.Document,
Expand Down
Loading