public Task WriteFragmentAsync(ArraySegment <byte> buffer, bool isUtf8Encoded, bool isFinalFragment) { TaskCompletionSource <object> tcs = new TaskCompletionSource <object>(); // The buffer will be read from asynchronously by unmanaged code, so we require that it remain pinned PinnedArraySegment <byte> pinnedBuffer = new PinnedArraySegment <byte>(buffer); // Callback will always be called (since it is responsible for cleanup), even if completed synchronously CompletionCallback callback = (hrError, cbIO, fUtf8Encoded, fFinalFragment, fClose) => { try { ThrowExceptionForHR(hrError); tcs.TrySetResult(null); // regular completion } catch (Exception ex) { tcs.TrySetException(ex); // exceptional completion } finally { // Always free the buffer to prevent a memory leak pinnedBuffer.Dispose(); } }; IntPtr completionContext = GCUtil.RootObject(callback); // update perf counter with count of data written to wire _perfCounters.IncrementCounter(AppPerfCounter.REQUEST_BYTES_OUT_WEBSOCKETS, pinnedBuffer.Count); // Call the underlying implementation; WriteFragment should never throw an exception int bytesSent = pinnedBuffer.Count; bool completionExpected; int hr = _context.WriteFragment( pData: pinnedBuffer.Pointer, pcbSent: ref bytesSent, fAsync: true, fUtf8Encoded: isUtf8Encoded, fFinalFragment: isFinalFragment, pfnCompletion: _asyncThunkAddress, pvCompletionContext: completionContext, pfCompletionExpected: out completionExpected); if (!completionExpected) { // Completed synchronously or error; the thunk and callback together handle cleanup AsyncCallbackThunk(hr, completionContext, bytesSent, isUtf8Encoded, isFinalFragment, fClose: false); } return(tcs.Task); }
/// <summary> /// Runs as java pass through. /// </summary> /// <param name="callingFrame">The calling frame.</param> /// <param name="service">The service.</param> /// <param name="list">The list.</param> /// <returns></returns> public ExecutionResult RunAsJavaPassThrough(StackFrame callingFrame, Type service, params object[] list) { var retval = ExecutionResult.Empty; var result = ExecutionResult.Empty; KeyValuePair <JniMethodDescription, Tuple <IEntity, IEntity, IEntity> >?found = null; var exceptions = new StringBuilder(Win32Helper.Max_BufferSizeForMessagesFromJni); var returnValueGetter = ReturnDelegateBasedOnType(retval); try { if (IsJvmLoaded.Value) { _perfCounters.IncrementCounter(Enums.PerfCounter.TotalRequests); // Increase "TotalRequest" performance counter var methodKey = new JniMethodDescription(callingFrame, service); // Let's retrieve method metadata from dictionary (if exists), otherwise we'll get it from database if (CachedJniMethods.ContainsKey(methodKey.MethodSignature)) { found = CachedJniMethods[methodKey.MethodSignature]; _perfCounters.IncrementCounter(Enums.PerfCounter.CachedJniMethodCall); // Increase "CachedJniMethodCall" performance counter } else { result = _dataservice.GetMethodInformationForJniCall(service, callingFrame, list); _perfCounters.IncrementCounter(Enums.PerfCounter.DbJniMethodCall); // Increase "DbJniMethodCall" performance counter var metadata = result.Tag as Tuple <IEntity, IEntity, IEntity>; if (result.IsSuccess && metadata != null) { found = new KeyValuePair <JniMethodDescription, Tuple <IEntity, IEntity, IEntity> >(methodKey, metadata); CachedJniMethods.Add(methodKey.MethodSignature, found.Value); } } RunAsJavaPassThroughHelper(callingFrame, list, found, retval, methodKey, returnValueGetter, exceptions); } } catch (Exception e) { retval.LastExceptionIfAny = e; } return(retval); }
/// <summary> /// Builds the proxy assembly helper. /// </summary> /// <param name="codeFiles">The code files.</param> /// <param name="workFolder">The work folder.</param> /// <param name="jarInformationFile">The jar information file.</param> /// <returns></returns> private ExecutionResult BuildProxyAssemblyHelper(Dictionary <string, StringBuilder> codeFiles, string workFolder, string jarInformationFile) { var tryAgain = true; CompilerResults result; var newFiles = new List <string>(); var retval = ExecutionResult.Empty; var assemblyName = jarInformationFile.Replace(".xml", ".dll"); try { // If work folder doesn't exist, we'll create it if (!Directory.Exists(workFolder)) { Directory.CreateDirectory(workFolder); } using (var cp = CodeDomProvider.CreateProvider("CSharp")) { foreach (var i in codeFiles) { var fileName = $@"{workFolder}\{i.Key.Substring(0, i.Key.IndexOf('|'))}.cs"; // Let's make sure file doesn't exist if (File.Exists(fileName)) { File.Delete(fileName); } File.WriteAllText(fileName, i.Value.ToString()); // and create the source file newFiles.Add(fileName); } var referenceAssemblies = GetReferenceAssemblies(); var cParams = new CompilerParameters(new string[] { "System.Linq.dll", "System.ServiceModel.dll", "System.ServiceModel.Web.dll" }) { GenerateExecutable = false, OutputAssembly = assemblyName, CompilerOptions = "/platform:x64" }; // Should we load reference assemblies into AppDomain or not? var loadedAlready = Assembly.GetExecutingAssembly().Modules.Any(p => p.Name.Contains("Simplicity.dotNet.")); referenceAssemblies.ForEach(_ => { cParams.ReferencedAssemblies.Add(_); if (!loadedAlready) // If reference assemblies hasn't been loaded, we'll load them { Assembly.Load(AssemblyName.GetAssemblyName(_)); } }); // We'll compile those files that were parsed Ok do { result = cp.CompileAssemblyFromFile(cParams, newFiles.ToArray()); if (result.Errors.Count == 0) { tryAgain = false; } else { var errors = result.Errors.Cast <CompilerError>(); var filesToExclude = newFiles.Where(p => !errors.Any(p2 => string.Equals(p, p2.FileName, StringComparison.OrdinalIgnoreCase))); newFiles = filesToExclude.ToList(); } } while (tryAgain); // Any errors at compilation? if (result.Errors.Count > 0) { retval.Tag = result.Errors; } else { result.TempFiles.KeepFiles = false; _perfCounters.IncrementCounter(Enums.PerfCounter.ProxyGeneration); // Increase "ProxyGeneration" performance counter retval = PerformCleanUp(newFiles, jarInformationFile, result.PathToAssembly, result.TempFiles.Delete); } } } catch (Exception e) { retval.LastExceptionIfAny = e; } return(retval); }