/// <summary> /// Cleanup the clients connection /// </summary> /// <remarks> /// <para> /// Close the socket connection. /// </para> /// </remarks> public void Dispose() { try { if (m_writer != null) { CompatibilityExtensions.Close(m_writer); m_writer = null; } } catch { } if (m_socket != null) { try { m_socket.Shutdown(SocketShutdown.Both); } catch { } try { CompatibilityExtensions.Close(m_socket); } catch { } m_socket = null; } }
/// <summary> /// Helper method to close <paramref name="stream" /> under CurrentAppender's SecurityContext. /// </summary> /// <remarks> /// Does not set <paramref name="stream" /> to null. /// </remarks> /// <param name="stream"></param> protected void CloseStream(Stream stream) { using (CurrentAppender.SecurityContext.Impersonate(this)) { CompatibilityExtensions.Close(stream); } }
/// <summary> /// Close all network connections /// </summary> /// <remarks> /// <para> /// Make sure we close all network connections /// </para> /// </remarks> public void Dispose() { foreach (SocketClient client in m_clients) { client.Dispose(); } m_clients.Clear(); Socket serverSocket = m_serverSocket; m_serverSocket = null; try { serverSocket.Shutdown(SocketShutdown.Both); } catch { } try { CompatibilityExtensions.Close(serverSocket); } catch { } }
public override Task ClientStreamWriteAsync(TRequest message) { // The retry client stream writer prevents multiple threads from reaching here. return(DoClientStreamActionAsync(async call => { CompatibilityExtensions.Assert(call.ClientStreamWriter != null); if (ClientStreamWriteOptions != null) { call.ClientStreamWriter.WriteOptions = ClientStreamWriteOptions; } await call.WriteClientStreamAsync(WriteNewMessage, message).ConfigureAwait(false); lock (Lock) { BufferedCurrentMessage = false; } if (ClientStreamComplete) { await call.ClientStreamWriter.CompleteAsync().ConfigureAwait(false); } })); }
/// <summary> /// Closes the UDP connection and releases all resources associated with /// this <see cref="T:log4net.Appender.UdpAppender" /> instance. /// </summary> /// <remarks> /// <para> /// Disables the underlying <see cref="T:System.Net.Sockets.UdpClient" /> and releases all managed /// and unmanaged resources associated with the <see cref="T:log4net.Appender.UdpAppender" />. /// </para> /// </remarks> protected override void OnClose() { base.OnClose(); if (Client != null) { CompatibilityExtensions.Close(Client); Client = null; } }
/// <summary> /// Gets the repository name and repository type for the specified assembly. /// </summary> /// <param name="assembly">The assembly that has a <see cref="T:log4net.Config.RepositoryAttribute" />.</param> /// <param name="repositoryName">in/out param to hold the repository name to use for the assembly, caller should set this to the default value before calling.</param> /// <param name="repositoryType">in/out param to hold the type of the repository to create for the assembly, caller should set this to the default value before calling.</param> /// <exception cref="T:System.ArgumentNullException"><paramref name="assembly" /> is <see langword="null" />.</exception> private void GetInfoForAssembly(Assembly assembly, ref string repositoryName, ref Type repositoryType) { if ((object)assembly == null) { throw new ArgumentNullException("assembly"); } try { LogLog.Debug(declaringType, "Assembly [" + assembly.FullName + "] Loaded From [" + SystemInfo.AssemblyLocationInfo(assembly) + "]"); } catch { } try { object[] array = assembly.GetCustomAttributes(typeof(RepositoryAttribute)).ToArray(); if (array == null || array.Length == 0) { LogLog.Debug(declaringType, "Assembly [" + assembly + "] does not have a RepositoryAttribute specified."); } else { if (array.Length > 1) { LogLog.Error(declaringType, "Assembly [" + assembly + "] has multiple log4net.Config.RepositoryAttribute assembly attributes. Only using first occurrence."); } RepositoryAttribute repositoryAttribute = array[0] as RepositoryAttribute; if (repositoryAttribute == null) { LogLog.Error(declaringType, "Assembly [" + assembly + "] has a RepositoryAttribute but it does not!."); } else { if (repositoryAttribute.Name != null) { repositoryName = repositoryAttribute.Name; } if ((object)repositoryAttribute.RepositoryType != null) { if (CompatibilityExtensions.IsAssignableFrom(typeof(ILoggerRepository), repositoryAttribute.RepositoryType)) { repositoryType = repositoryAttribute.RepositoryType; } else { LogLog.Error(declaringType, "DefaultRepositorySelector: Repository Type [" + repositoryAttribute.RepositoryType + "] must implement the ILoggerRepository interface."); } } } } } catch (Exception exception) { LogLog.Error(declaringType, "Unhandled exception in GetInfoForAssembly", exception); } }
private static void InternalConfigure(ILoggerRepository repository, Uri configUri) { LogLog.Debug(declaringType, "configuring repository [" + repository.Name + "] using URI [" + configUri + "]"); if (configUri == null) { LogLog.Error(declaringType, "Configure called with null 'configUri' parameter"); return; } if (configUri.IsFile) { InternalConfigure(repository, new FileInfo(configUri.LocalPath)); return; } WebRequest webRequest = null; try { webRequest = WebRequest.Create(configUri); } catch (Exception exception) { LogLog.Error(declaringType, "Failed to create WebRequest for URI [" + configUri + "]", exception); } if (webRequest != null) { try { webRequest.Credentials = CredentialCache.DefaultCredentials; } catch { } try { WebResponse result = webRequest.GetResponseAsync().GetAwaiter().GetResult(); if (result != null) { try { using (Stream configStream = result.GetResponseStream()) { InternalConfigure(repository, configStream); } } finally { CompatibilityExtensions.Close(result); } } } catch (Exception exception2) { LogLog.Error(declaringType, "Failed to request config from URI [" + configUri + "]", exception2); } } }
/// <summary> /// Creates the plugin object defined by this attribute. /// </summary> /// <remarks> /// <para> /// Creates the instance of the <see cref="T:log4net.Plugin.IPlugin" /> object as /// specified by this attribute. /// </para> /// </remarks> /// <returns>The plugin object.</returns> public IPlugin CreatePlugin() { Type type = m_type; if (!CompatibilityExtensions.IsAssignableFrom(typeof(IPlugin), type)) { throw new LogException("Plugin type [" + type.FullName + "] does not implement the log4net.IPlugin interface"); } return((IPlugin)Activator.CreateInstance(type)); }
/// <summary> /// Add a converter to this PatternLayout /// </summary> /// <param name="converterInfo">the converter info</param> /// <remarks> /// <para> /// This version of the method is used by the configurator. /// Programmatic users should use the alternative <see cref="M:AddConverter(string,Type)" /> method. /// </para> /// </remarks> public void AddConverter(ConverterInfo converterInfo) { if (converterInfo == null) { throw new ArgumentNullException("converterInfo"); } if (!CompatibilityExtensions.IsAssignableFrom(typeof(PatternConverter), converterInfo.Type)) { throw new ArgumentException("The converter type specified [" + converterInfo.Type + "] must be a subclass of log4net.Util.PatternConverter", "converterInfo"); } m_instanceRulesRegistry[converterInfo.Name] = converterInfo; }
/// <summary> /// Lookups the type converter to use as specified by the attributes on the /// destination type. /// </summary> /// <param name="destinationType">The type being converted to.</param> /// <returns> /// The type converter instance to use for type conversions or <c>null</c> /// if no type converter is found. /// </returns> private static object GetConverterFromAttribute(Type destinationType) { object[] customAttributes = CompatibilityExtensions.GetCustomAttributes(destinationType, typeof(TypeConverterAttribute), inherit: true); if (customAttributes != null && customAttributes.Length != 0) { TypeConverterAttribute typeConverterAttribute = customAttributes[0] as TypeConverterAttribute; if (typeConverterAttribute != null) { return(CreateConverterInstance(SystemInfo.GetTypeFromString(destinationType, typeConverterAttribute.ConverterTypeName, throwOnError: false, ignoreCase: true))); } } return(null); }
/// <summary> /// Creates a new repository selector. /// </summary> /// <param name="defaultRepositoryType">The type of the repositories to create, must implement <see cref="T:log4net.Repository.ILoggerRepository" /></param> /// <remarks> /// <para> /// Create an new repository selector. /// The default type for repositories must be specified, /// an appropriate value would be <see cref="T:log4net.Repository.Hierarchy.Hierarchy" />. /// </para> /// </remarks> /// <exception cref="T:System.ArgumentNullException"><paramref name="defaultRepositoryType" /> is <see langword="null" />.</exception> /// <exception cref="T:System.ArgumentOutOfRangeException"><paramref name="defaultRepositoryType" /> does not implement <see cref="T:log4net.Repository.ILoggerRepository" />.</exception> public DefaultRepositorySelector(Type defaultRepositoryType) { if ((object)defaultRepositoryType == null) { throw new ArgumentNullException("defaultRepositoryType"); } if (!CompatibilityExtensions.IsAssignableFrom(typeof(ILoggerRepository), defaultRepositoryType)) { throw SystemInfo.CreateArgumentOutOfRangeException("defaultRepositoryType", defaultRepositoryType, "Parameter: defaultRepositoryType, Value: [" + defaultRepositoryType + "] out of range. Argument must implement the ILoggerRepository interface"); } m_defaultRepositoryType = defaultRepositoryType; LogLog.Debug(declaringType, "defaultRepositoryType [" + m_defaultRepositoryType + "]"); }
private async Task HedgingDelayAsync(TimeSpan hedgingDelay) { CompatibilityExtensions.Assert(_hedgingDelayCts != null); CompatibilityExtensions.Assert(_delayInterruptTcs != null); while (true) { CompatibilityExtensions.Assert(_hedgingDelayCts != null); var completedTask = await Task.WhenAny(Task.Delay(hedgingDelay, _hedgingDelayCts.Token), _delayInterruptTcs.Task).ConfigureAwait(false); if (completedTask != _delayInterruptTcs.Task) { // Task.Delay won. Check CTS to see if it won because of cancellation. _hedgingDelayCts.Token.ThrowIfCancellationRequested(); return; } else { // Cancel the Task.Delay that's no longer needed. // https://github.com/davidfowl/AspNetCoreDiagnosticScenarios/blob/519ef7d231c01116f02bc04354816a735f2a36b6/AsyncGuidance.md#using-a-timeout _hedgingDelayCts.Cancel(); } lock (Lock) { // If we reaching this point then the delay was interrupted. // Need to recreate the delay TCS/CTS for the next cycle. _delayInterruptTcs = new TaskCompletionSource <object?>(TaskCreationOptions.RunContinuationsAsynchronously); _hedgingDelayCts = new CancellationTokenSource(); // Interrupt could come from a pushback, or a failing call with a non-fatal status. if (_pushbackDelay != null) { // Use pushback value and delay again hedgingDelay = _pushbackDelay.GetValueOrDefault(); _pushbackDelay = null; } else { // Immediately return for non-fatal status. return; } } } }
private static void InternalConfigure(ILoggerRepository repository, FileInfo configFile) { LogLog.Debug(declaringType, "configuring repository [" + repository.Name + "] using file [" + configFile + "]"); if (configFile == null) { LogLog.Error(declaringType, "Configure called with null 'configFile' parameter"); } else if (File.Exists(configFile.FullName)) { FileStream fileStream = null; int num = 5; while (--num >= 0) { try { fileStream = configFile.Open(FileMode.Open, FileAccess.Read, FileShare.Read); } catch (IOException exception) { if (num == 0) { LogLog.Error(declaringType, "Failed to open XML config file [" + configFile.Name + "]", exception); fileStream = null; } Thread.Sleep(250); continue; } break; } if (fileStream != null) { try { InternalConfigure(repository, fileStream); } finally { CompatibilityExtensions.Close(fileStream); } } } else { LogLog.Debug(declaringType, "config file [" + configFile.FullName + "] not found. Configuration unchanged."); } }
/// <summary> /// Produces a formatted string. /// </summary> /// <param name="loggingEvent">The event being logged.</param> /// <param name="writer">The TextWriter to write the formatted event to</param> /// <remarks> /// <para> /// Format the <see cref="T:log4net.Core.LoggingEvent" /> and write it to the <see cref="T:System.IO.TextWriter" />. /// </para> /// <para> /// This method creates an <see cref="T:System.Xml.XmlTextWriter" /> that writes to the /// <paramref name="writer" />. The <see cref="T:System.Xml.XmlTextWriter" /> is passed /// to the <see cref="M:log4net.Layout.XmlLayoutBase.FormatXml(System.Xml.XmlWriter,log4net.Core.LoggingEvent)" /> method. Subclasses should override the /// <see cref="M:log4net.Layout.XmlLayoutBase.FormatXml(System.Xml.XmlWriter,log4net.Core.LoggingEvent)" /> method rather than this method. /// </para> /// </remarks> public override void Format(TextWriter writer, LoggingEvent loggingEvent) { if (loggingEvent == null) { throw new ArgumentNullException("loggingEvent"); } XmlWriterSettings settings = new XmlWriterSettings { Indent = false, OmitXmlDeclaration = true }; XmlWriter xmlWriter = XmlWriter.Create(new ProtectCloseTextWriter(writer), settings); FormatXml(xmlWriter, loggingEvent); xmlWriter.WriteWhitespace(SystemInfo.NewLine); CompatibilityExtensions.Close(xmlWriter); }
public override void TearDown() { if (indexWriter != null) { indexWriter.Dispose(); indexWriter = null; } if (indexReader != null) { indexReader.Dispose(); indexReader = null; } if (directory != null) { directory.Dispose(); directory = null; } CompatibilityExtensions.PurgeSpatialCaches(null); base.TearDown(); }
/// <summary> /// Is this <paramref name="loggingEvent" /> the triggering event? /// </summary> /// <param name="loggingEvent">The event to check</param> /// <returns>This method returns <c>true</c>, if the logging event Exception /// Type is <see cref="P:log4net.Core.ExceptionEvaluator.ExceptionType" />. /// Otherwise it returns <c>false</c></returns> /// <remarks> /// <para> /// This evaluator will trigger if the Exception Type of the event /// passed to <see cref="M:IsTriggeringEvent(LoggingEvent)" /> /// is <see cref="P:log4net.Core.ExceptionEvaluator.ExceptionType" />. /// </para> /// </remarks> public bool IsTriggeringEvent(LoggingEvent loggingEvent) { if (loggingEvent == null) { throw new ArgumentNullException("loggingEvent"); } if (m_triggerOnSubclass && loggingEvent.ExceptionObject != null) { Type type = ((object)loggingEvent.ExceptionObject).GetType(); if ((object)type != m_type) { return(CompatibilityExtensions.IsSubclassOf(type, m_type)); } return(true); } if (!m_triggerOnSubclass && loggingEvent.ExceptionObject != null) { return((object)((object)loggingEvent.ExceptionObject).GetType() == m_type); } return(false); }
/// <summary> /// Converts an object to the target type. /// </summary> /// <param name="sourceInstance">The object to convert to the target type.</param> /// <param name="targetType">The type to convert to.</param> /// <returns>The converted object.</returns> /// <remarks> /// <para> /// Converts an object to the target type. /// </para> /// </remarks> public static object ConvertTypeTo(object sourceInstance, Type targetType) { Type type = sourceInstance.GetType(); if (CompatibilityExtensions.IsAssignableFrom(targetType, type)) { return(sourceInstance); } IConvertTo convertTo = ConverterRegistry.GetConvertTo(type, targetType); if (convertTo != null && convertTo.CanConvertTo(targetType)) { return(convertTo.ConvertTo(sourceInstance, targetType)); } IConvertFrom convertFrom = ConverterRegistry.GetConvertFrom(targetType); if (convertFrom != null && convertFrom.CanConvertFrom(type)) { return(convertFrom.ConvertFrom(sourceInstance)); } throw new ArgumentException("Cannot convert source object [" + sourceInstance.ToString() + "] to target type [" + targetType.Name + "]", "sourceInstance"); }
/// <summary> /// Instantiates an object given a class name. /// </summary> /// <param name="className">The fully qualified class name of the object to instantiate.</param> /// <param name="superClass">The class to which the new object should belong.</param> /// <param name="defaultValue">The object to return in case of non-fulfillment.</param> /// <returns> /// An instance of the <paramref name="className" /> or <paramref name="defaultValue" /> /// if the object could not be instantiated. /// </returns> /// <remarks> /// <para> /// Checks that the <paramref name="className" /> is a subclass of /// <paramref name="superClass" />. If that test fails or the object could /// not be instantiated, then <paramref name="defaultValue" /> is returned. /// </para> /// </remarks> public static object InstantiateByClassName(string className, Type superClass, object defaultValue) { if (className != null) { try { Type typeFromString = SystemInfo.GetTypeFromString(superClass.GetTypeInfo().Assembly, className, throwOnError: true, ignoreCase: true); if (!CompatibilityExtensions.IsAssignableFrom(superClass, typeFromString)) { LogLog.Error(declaringType, "OptionConverter: A [" + className + "] object is not assignable to a [" + superClass.FullName + "] variable."); return(defaultValue); } return(Activator.CreateInstance(typeFromString)); } catch (Exception exception) { LogLog.Error(declaringType, "Could not instantiate class [" + className + "].", exception); return(defaultValue); } } return(defaultValue); }
/// <summary> /// Creates the instance of the type converter. /// </summary> /// <param name="converterType">The type of the type converter.</param> /// <returns> /// The type converter instance to use for type conversions or <c>null</c> /// if no type converter is found. /// </returns> /// <remarks> /// <para> /// The type specified for the type converter must implement /// the <see cref="T:log4net.Util.TypeConverters.IConvertFrom" /> or <see cref="T:log4net.Util.TypeConverters.IConvertTo" /> interfaces /// and must have a public default (no argument) constructor. /// </para> /// </remarks> private static object CreateConverterInstance(Type converterType) { if ((object)converterType == null) { throw new ArgumentNullException("converterType", "CreateConverterInstance cannot create instance, converterType is null"); } if (CompatibilityExtensions.IsAssignableFrom(typeof(IConvertFrom), converterType) || CompatibilityExtensions.IsAssignableFrom(typeof(IConvertTo), converterType)) { try { return(Activator.CreateInstance(converterType)); } catch (Exception exception) { LogLog.Error(declaringType, "Cannot CreateConverterInstance of type [" + converterType.FullName + "], Exception in call to Activator.CreateInstance", exception); } } else { LogLog.Error(declaringType, "Cannot CreateConverterInstance of type [" + converterType.FullName + "], type does not implement IConvertFrom or IConvertTo"); } return(null); }
/// <summary> /// Checks if there is an appropriate type conversion from the source type to the target type. /// </summary> /// <param name="sourceType">The type to convert from.</param> /// <param name="targetType">The type to convert to.</param> /// <returns><c>true</c> if there is a conversion from the source type to the target type.</returns> /// <remarks> /// Checks if there is an appropriate type conversion from the source type to the target type. /// <para> /// </para> /// </remarks> public static bool CanConvertTypeTo(Type sourceType, Type targetType) { if ((object)sourceType == null || (object)targetType == null) { return(false); } if (CompatibilityExtensions.IsAssignableFrom(targetType, sourceType)) { return(true); } IConvertTo convertTo = ConverterRegistry.GetConvertTo(sourceType, targetType); if (convertTo != null && convertTo.CanConvertTo(targetType)) { return(true); } IConvertFrom convertFrom = ConverterRegistry.GetConvertFrom(targetType); if (convertFrom != null && convertFrom.CanConvertFrom(sourceType)) { return(true); } return(false); }
/// <summary> /// Parses a file size into a number. /// </summary> /// <param name="argValue">String to parse.</param> /// <param name="defaultValue">The default value.</param> /// <returns>The <see cref="T:System.Int64" /> value of <paramref name="argValue" />.</returns> /// <remarks> /// <para> /// Parses a file size of the form: number[KB|MB|GB] into a /// long value. It is scaled with the appropriate multiplier. /// </para> /// <para> /// <paramref name="defaultValue" /> is returned when <paramref name="argValue" /> /// cannot be converted to a <see cref="T:System.Int64" /> value. /// </para> /// </remarks> public static long ToFileSize(string argValue, long defaultValue) { if (argValue == null) { return(defaultValue); } string text = CompatibilityExtensions.ToUpper(argValue.Trim(), CultureInfo.InvariantCulture); long num = 1L; int length; if ((length = text.IndexOf("KB")) != -1) { num = 1024L; text = text.Substring(0, length); } else if ((length = text.IndexOf("MB")) != -1) { num = 1048576L; text = text.Substring(0, length); } else if ((length = text.IndexOf("GB")) != -1) { num = 1073741824L; text = text.Substring(0, length); } if (text != null) { text = text.Trim(); if (SystemInfo.TryParse(text, out long val)) { return(val * num); } LogLog.Error(declaringType, "OptionConverter: [" + text + "] is not in the correct file size syntax."); } return(defaultValue); }
/// <summary> /// Can the sourceType be converted to an <see cref="T:log4net.Layout.IRawLayout" /> /// </summary> /// <param name="sourceType">the source to be to be converted</param> /// <returns><c>true</c> if the source type can be converted to <see cref="T:log4net.Layout.IRawLayout" /></returns> /// <remarks> /// <para> /// Test if the <paramref name="sourceType" /> can be converted to a /// <see cref="T:log4net.Layout.IRawLayout" />. Only <see cref="T:log4net.Layout.ILayout" /> is supported /// as the <paramref name="sourceType" />. /// </para> /// </remarks> public bool CanConvertFrom(Type sourceType) { return(CompatibilityExtensions.IsAssignableFrom(typeof(ILayout), sourceType)); }
/// <summary> /// Creates an object as specified in XML. /// </summary> /// <param name="element">The XML element that contains the definition of the object.</param> /// <param name="defaultTargetType">The object type to use if not explicitly specified.</param> /// <param name="typeConstraint">The type that the returned object must be or must inherit from.</param> /// <returns>The object or <c>null</c></returns> /// <remarks> /// <para> /// Parse an XML element and create an object instance based on the configuration /// data. /// </para> /// <para> /// The type of the instance may be specified in the XML. If not /// specified then the <paramref name="defaultTargetType" /> is used /// as the type. However the type is specified it must support the /// <paramref name="typeConstraint" /> type. /// </para> /// </remarks> protected object CreateObjectFromXml(XmlElement element, Type defaultTargetType, Type typeConstraint) { Type type = null; string attribute = element.GetAttribute("type"); if (attribute == null || attribute.Length == 0) { if ((object)defaultTargetType == null) { LogLog.Error(declaringType, "Object type not specified. Cannot create object of type [" + typeConstraint.FullName + "]. Missing Value or Type."); return(null); } type = defaultTargetType; } else { try { type = SystemInfo.GetTypeFromString(GetType().GetTypeInfo().Assembly, attribute, throwOnError: true, ignoreCase: true); } catch (Exception exception) { LogLog.Error(declaringType, "Failed to find type [" + attribute + "]", exception); return(null); } } bool flag = false; if ((object)typeConstraint != null && !CompatibilityExtensions.IsAssignableFrom(typeConstraint, type)) { if (!OptionConverter.CanConvertTypeTo(type, typeConstraint)) { LogLog.Error(declaringType, "Object type [" + type.FullName + "] is not assignable to type [" + typeConstraint.FullName + "]. There are no acceptable type conversions."); return(null); } flag = true; } object obj = null; try { obj = Activator.CreateInstance(type); } catch (Exception ex) { LogLog.Error(declaringType, "XmlHierarchyConfigurator: Failed to construct object of type [" + type.FullName + "] Exception: " + ex.ToString()); } foreach (XmlNode childNode in element.ChildNodes) { if (childNode.NodeType == XmlNodeType.Element) { SetParameter((XmlElement)childNode, obj); } } (obj as IOptionHandler)?.ActivateOptions(); if (flag) { return(OptionConverter.ConvertTypeTo(obj, typeConstraint)); } return(obj); }
/// <summary> /// Sets a parameter on an object. /// </summary> /// <param name="element">The parameter element.</param> /// <param name="target">The object to set the parameter on.</param> /// <remarks> /// The parameter name must correspond to a writable property /// on the object. The value of the parameter is a string, /// therefore this function will attempt to set a string /// property first. If unable to set a string property it /// will inspect the property and its argument type. It will /// attempt to call a static method called <c>Parse</c> on the /// type of the property. This method will take a single /// string argument and return a value that can be used to /// set the property. /// </remarks> protected void SetParameter(XmlElement element, object target) { string text = element.GetAttribute("name"); if (element.LocalName != "param" || text == null || text.Length == 0) { text = element.LocalName; } Type type = target.GetType(); Type type2 = null; PropertyInfo propertyInfo = null; MethodInfo methodInfo = null; propertyInfo = type.GetProperty(text, BindingFlags.IgnoreCase | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if ((object)propertyInfo != null && propertyInfo.CanWrite) { type2 = propertyInfo.PropertyType; } else { propertyInfo = null; methodInfo = FindMethodInfo(type, text); if ((object)methodInfo != null) { type2 = methodInfo.GetParameters()[0].ParameterType; } } if ((object)type2 == null) { LogLog.Error(declaringType, "XmlHierarchyConfigurator: Cannot find Property [" + text + "] to set object on [" + target.ToString() + "]"); return; } string text2 = null; if (element.GetAttributeNode("value") != null) { text2 = element.GetAttribute("value"); } else if (element.HasChildNodes) { foreach (XmlNode childNode in element.ChildNodes) { if (childNode.NodeType == XmlNodeType.CDATA || childNode.NodeType == XmlNodeType.Text) { text2 = ((text2 != null) ? (text2 + childNode.InnerText) : childNode.InnerText); } } } if (text2 != null) { Type type3 = null; string attribute = element.GetAttribute("type"); if (attribute != null && attribute.Length > 0) { try { Type typeFromString = SystemInfo.GetTypeFromString(GetType().GetTypeInfo().Assembly, attribute, throwOnError: true, ignoreCase: true); LogLog.Debug(declaringType, "Parameter [" + text + "] specified subtype [" + typeFromString.FullName + "]"); if (!CompatibilityExtensions.IsAssignableFrom(type2, typeFromString)) { if (OptionConverter.CanConvertTypeTo(typeFromString, type2)) { type3 = type2; type2 = typeFromString; } else { LogLog.Error(declaringType, "subtype [" + typeFromString.FullName + "] set on [" + text + "] is not a subclass of property type [" + type2.FullName + "] and there are no acceptable type conversions."); } } else { type2 = typeFromString; } } catch (Exception exception) { LogLog.Error(declaringType, "Failed to find type [" + attribute + "] set on [" + text + "]", exception); } } object obj = ConvertStringTo(type2, text2); if (obj != null && (object)type3 != null) { LogLog.Debug(declaringType, "Performing additional conversion of value from [" + obj.GetType().Name + "] to [" + type3.Name + "]"); obj = OptionConverter.ConvertTypeTo(obj, type3); } if (obj != null) { if ((object)propertyInfo != null) { LogLog.Debug(declaringType, "Setting Property [" + propertyInfo.Name + "] to " + obj.GetType().Name + " value [" + obj.ToString() + "]"); try { propertyInfo.SetValue(target, obj, null); } catch (TargetInvocationException ex) { LogLog.Error(declaringType, "Failed to set parameter [" + propertyInfo.Name + "] on object [" + target + "] using value [" + obj + "]", ex.InnerException); } } else if ((object)methodInfo != null) { LogLog.Debug(declaringType, "Setting Collection Property [" + methodInfo.Name + "] to " + obj.GetType().Name + " value [" + obj.ToString() + "]"); try { methodInfo.Invoke(target, new object[1] { obj }); } catch (TargetInvocationException ex2) { LogLog.Error(declaringType, "Failed to set parameter [" + text + "] on object [" + target + "] using value [" + obj + "]", ex2.InnerException); } } } else { LogLog.Warn(declaringType, "Unable to set property [" + text + "] on object [" + target + "] using value [" + text2 + "] (with acceptable conversion types)"); } return; } object obj2 = null; if ((object)type2 == typeof(string) && !HasAttributesOrElements(element)) { obj2 = ""; } else { Type defaultTargetType = null; if (IsTypeConstructible(type2)) { defaultTargetType = type2; } obj2 = CreateObjectFromXml(element, defaultTargetType, type2); } if (obj2 == null) { LogLog.Error(declaringType, "Failed to create object to set param: " + text); } else if ((object)propertyInfo != null) { LogLog.Debug(declaringType, "Setting Property [" + propertyInfo.Name + "] to object [" + obj2 + "]"); try { propertyInfo.SetValue(target, obj2, null); } catch (TargetInvocationException ex3) { LogLog.Error(declaringType, "Failed to set parameter [" + propertyInfo.Name + "] on object [" + target + "] using value [" + obj2 + "]", ex3.InnerException); } } else if ((object)methodInfo != null) { LogLog.Debug(declaringType, "Setting Collection Property [" + methodInfo.Name + "] to object [" + obj2 + "]"); try { methodInfo.Invoke(target, new object[1] { obj2 }); } catch (TargetInvocationException ex4) { LogLog.Error(declaringType, "Failed to set parameter [" + methodInfo.Name + "] on object [" + target + "] using value [" + obj2 + "]", ex4.InnerException); } } }
private async Task StartCall(Action <GrpcCall <TRequest, TResponse> > startCallFunc) { GrpcCall <TRequest, TResponse> call; lock (Lock) { if (CommitedCallTask.IsCompletedSuccessfully()) { // Call has already been commited. This could happen if written messages exceed // buffer limits, which causes the call to immediately become commited and to clear buffers. return; } OnStartingAttempt(); call = HttpClientCallInvoker.CreateGrpcCall <TRequest, TResponse>(Channel, Method, Options, AttemptCount); _activeCalls.Add(call); startCallFunc(call); SetNewActiveCallUnsynchronized(call); } Status?responseStatus; HttpResponseMessage?httpResponse = null; try { call.CancellationToken.ThrowIfCancellationRequested(); CompatibilityExtensions.Assert(call._httpResponseTask != null, "Request should have been made if call is not preemptively cancelled."); httpResponse = await call._httpResponseTask.ConfigureAwait(false); responseStatus = GrpcCall.ValidateHeaders(httpResponse, out _); } catch (Exception ex) { call.ResolveException(GrpcCall <TRequest, TResponse> .ErrorStartingCallMessage, ex, out responseStatus, out _); } if (CancellationTokenSource.IsCancellationRequested) { CommitCall(call, CommitReason.Canceled); return; } // Check to see the response returned from the server makes the call commited // Null status code indicates the headers were valid and a "Response-Headers" response // was received from the server. // https://github.com/grpc/proposal/blob/master/A6-client-retries.md#when-retries-are-valid if (responseStatus == null) { // Headers were returned. We're commited. CommitCall(call, CommitReason.ResponseHeadersReceived); // Wait until the call has finished and then check its status code // to update retry throttling tokens. var status = await call.CallTask.ConfigureAwait(false); if (status.StatusCode == StatusCode.OK) { RetryAttemptCallSuccess(); } } else { var status = responseStatus.Value; var retryPushbackMS = GetRetryPushback(httpResponse); if (retryPushbackMS < 0) { RetryAttemptCallFailure(); } else if (_hedgingPolicy.NonFatalStatusCodes.Contains(status.StatusCode)) { // Needs to happen before interrupt. RetryAttemptCallFailure(); // No need to interrupt if we started with no delay and all calls // have already been made when hedging starting. if (_delayInterruptTcs != null) { lock (Lock) { if (retryPushbackMS >= 0) { _pushbackDelay = TimeSpan.FromMilliseconds(retryPushbackMS.GetValueOrDefault()); } _delayInterruptTcs.TrySetResult(null); } } } else { CommitCall(call, CommitReason.FatalStatusCode); } } lock (Lock) { if (IsDeadlineExceeded()) { // Deadline has been exceeded so immediately commit call. CommitCall(call, CommitReason.DeadlineExceeded); } else if (_activeCalls.Count == 1 && AttemptCount >= MaxRetryAttempts) { // This is the last active call and no more will be made. CommitCall(call, CommitReason.ExceededAttemptCount); } else if (_activeCalls.Count == 1 && IsRetryThrottlingActive()) { // This is the last active call and throttling is active. CommitCall(call, CommitReason.Throttled); } else { // Call isn't used and can be cancelled. // Note that the call could have already been removed and disposed if the // hedging call has been finalized or disposed. if (_activeCalls.Remove(call)) { call.Dispose(); } } } }
public async Task AsyncUnaryCall_CompressMetadataSentWithRequest_RequestMessageCompressed(bool compressionDisabledOnOptions) { // Arrange HttpRequestMessage?httpRequestMessage = null; HelloRequest? helloRequest = null; bool?isRequestNotCompressed = null; var httpClient = ClientTestHelpers.CreateTestClient(async request => { httpRequestMessage = request; var requestData = await request.Content !.ReadAsByteArrayAsync().DefaultTimeout(); isRequestNotCompressed = requestData[0] == 0; helloRequest = await StreamSerializationHelper.ReadMessageAsync( new MemoryStream(requestData), ClientTestHelpers.ServiceMethod.RequestMarshaller.ContextualDeserializer, "gzip", maximumMessageSize: null, GrpcProtocolConstants.DefaultCompressionProviders, singleMessage: true, CancellationToken.None); HelloReply reply = new HelloReply { Message = "Hello world" }; var streamContent = await ClientTestHelpers.CreateResponseContent(reply).DefaultTimeout(); return(ResponseUtils.CreateResponse(HttpStatusCode.OK, streamContent)); }); var compressionProviders = GrpcProtocolConstants.DefaultCompressionProviders.Values.ToList(); compressionProviders.Add(new TestCompressionProvider()); var invoker = HttpClientCallInvokerFactory.Create(httpClient, configure: o => o.CompressionProviders = compressionProviders); var compressionMetadata = CreateClientCompressionMetadata("gzip"); var callOptions = new CallOptions(headers: compressionMetadata); if (compressionDisabledOnOptions) { callOptions = callOptions.WithWriteOptions(new WriteOptions(WriteFlags.NoCompress)); } // Act var call = invoker.AsyncUnaryCall <HelloRequest, HelloReply>(ClientTestHelpers.ServiceMethod, string.Empty, callOptions, new HelloRequest { Name = "Hello" }); // Assert var response = await call.ResponseAsync; Assert.IsNotNull(response); Assert.AreEqual("Hello world", response.Message); CompatibilityExtensions.Assert(httpRequestMessage != null); Assert.AreEqual("identity,gzip,test", httpRequestMessage.Headers.GetValues(GrpcProtocolConstants.MessageAcceptEncodingHeader).Single()); Assert.AreEqual("gzip", httpRequestMessage.Headers.GetValues(GrpcProtocolConstants.MessageEncodingHeader).Single()); Assert.AreEqual(false, httpRequestMessage.Headers.Contains(GrpcProtocolConstants.CompressionRequestAlgorithmHeader)); CompatibilityExtensions.Assert(helloRequest != null); Assert.AreEqual("Hello", helloRequest.Name); Assert.AreEqual(compressionDisabledOnOptions, isRequestNotCompressed); }
private async Task StartRetry(Action <GrpcCall <TRequest, TResponse> > startCallFunc) { Log.StartingRetryWorker(Logger); try { // This is the main retry loop. It will: // 1. Check the result of the active call was successful. // 2. If it was unsuccessful then evaluate if the call can be retried. // 3. If it can be retried then start a new active call and begin again. while (true) { GrpcCall <TRequest, TResponse> currentCall; lock (Lock) { // Start new call. OnStartingAttempt(); currentCall = _activeCall = HttpClientCallInvoker.CreateGrpcCall <TRequest, TResponse>(Channel, Method, Options, AttemptCount); startCallFunc(currentCall); if (CommitedCallTask.IsCompletedSuccessfully()) { // Call has already been commited. This could happen if written messages exceed // buffer limits, which causes the call to immediately become commited and to clear buffers. return; } SetNewActiveCallUnsynchronized(currentCall); } Status?responseStatus; HttpResponseMessage?httpResponse = null; try { currentCall.CancellationToken.ThrowIfCancellationRequested(); CompatibilityExtensions.Assert(currentCall._httpResponseTask != null, "Request should have been made if call is not preemptively cancelled."); httpResponse = await currentCall._httpResponseTask.ConfigureAwait(false); responseStatus = GrpcCall.ValidateHeaders(httpResponse, out _); } catch (Exception ex) { currentCall.ResolveException(GrpcCall <TRequest, TResponse> .ErrorStartingCallMessage, ex, out responseStatus, out _); } CancellationTokenSource.Token.ThrowIfCancellationRequested(); // Check to see the response returned from the server makes the call commited // Null status code indicates the headers were valid and a "Response-Headers" response // was received from the server. // https://github.com/grpc/proposal/blob/master/A6-client-retries.md#when-retries-are-valid if (responseStatus == null) { // Headers were returned. We're commited. CommitCall(currentCall, CommitReason.ResponseHeadersReceived); responseStatus = await currentCall.CallTask.ConfigureAwait(false); if (responseStatus.GetValueOrDefault().StatusCode == StatusCode.OK) { RetryAttemptCallSuccess(); } // Commited so exit retry loop. return; } if (CommitedCallTask.IsCompletedSuccessfully()) { // Call has already been commited. This could happen if written messages exceed // buffer limits, which causes the call to immediately become commited and to clear buffers. return; } Status status = responseStatus.Value; var retryPushbackMS = GetRetryPushback(httpResponse); // Failures only count towards retry throttling if they have a known, retriable status. // This stops non-transient statuses, e.g. INVALID_ARGUMENT, from triggering throttling. if (_retryPolicy.RetryableStatusCodes.Contains(status.StatusCode) || retryPushbackMS < 0) { RetryAttemptCallFailure(); } var result = EvaluateRetry(status, retryPushbackMS); Log.RetryEvaluated(Logger, status.StatusCode, AttemptCount, result == null); if (result == null) { TimeSpan delayDuration; if (retryPushbackMS != null) { delayDuration = TimeSpan.FromMilliseconds(retryPushbackMS.GetValueOrDefault()); _nextRetryDelayMilliseconds = retryPushbackMS.GetValueOrDefault(); } else { delayDuration = TimeSpan.FromMilliseconds(Channel.GetRandomNumber(0, Convert.ToInt32(_nextRetryDelayMilliseconds))); } Log.StartingRetryDelay(Logger, delayDuration); await Task.Delay(delayDuration, CancellationTokenSource.Token).ConfigureAwait(false); _nextRetryDelayMilliseconds = CalculateNextRetryDelay(); // Check if dispose was called on call. CancellationTokenSource.Token.ThrowIfCancellationRequested(); // Clean up the failed call. currentCall.Dispose(); } else { // Handle the situation where the call failed with a non-deadline status, but retry // didn't happen because of deadline exceeded. IGrpcCall <TRequest, TResponse> resolvedCall = (IsDeadlineExceeded() && !(currentCall.CallTask.IsCompletedSuccessfully() && currentCall.CallTask.Result.StatusCode == StatusCode.DeadlineExceeded)) ? CreateStatusCall(GrpcProtocolConstants.DeadlineExceededStatus) : currentCall; // Can't retry. // Signal public API exceptions that they should finish throwing and then exit the retry loop. CommitCall(resolvedCall, result.GetValueOrDefault()); return; } } } catch (Exception ex) { HandleUnexpectedError(ex); } finally { Log.StoppingRetryWorker(Logger); } }