@@ -78,8 +78,9 @@ namespace NLog.Internal
         /// </summary>
         /// <param name="exception">The exception to check.</param>
         /// <param name="loggerContext">Target context of the exception.</param>
+        /// <param name="logFactory">For checking <see cref="LogFactory.ThrowExceptions"/> and <see cref="LogFactory.ThrowConfigExceptions"/>. Falls back to <see cref="LogManager"/> </param>
         /// <returns><c>true</c>if the <paramref name="exception"/> must be rethrown, <c>false</c> otherwise.</returns>
-        public static bool MustBeRethrown(this Exception exception, IInternalLoggerContext loggerContext = null)
+        public static bool MustBeRethrown(this Exception exception, IInternalLoggerContext loggerContext = null, LogFactory logFactory = null)
         {
             if (exception.MustBeRethrownImmediately())
             {

//
// Copyright (c) 2004-2020 Jaroslaw Kowalski <jaak@jkowalski.net>, Kim Christensen, Julian Verdurmen
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
//
// * Redistributions of source code must retain the above copyright notice,
//   this list of conditions and the following disclaimer.
//
// * Redistributions in binary form must reproduce the above copyright notice,
//   this list of conditions and the following disclaimer in the documentation
//   and/or other materials provided with the distribution.
//
// * Neither the name of Jaroslaw Kowalski nor the names of its
//   contributors may be used to endorse or promote products derived from this
//   software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
// THE POSSIBILITY OF SUCH DAMAGE.
//

namespace NLog.Internal
{
    using System;
    using System.Threading;
    using NLog.Common;

    /// <summary>
    /// Helper class for dealing with exceptions.
    /// </summary>
    internal static class ExceptionHelper
    {
        private const string LoggedKey = "NLog.ExceptionLoggedToInternalLogger";

        /// <summary>
        /// Mark this exception as logged to the <see cref="InternalLogger"/>.
        /// </summary>
        /// <param name="exception"></param>
        /// <returns></returns>
        public static void MarkAsLoggedToInternalLogger(this Exception exception)
        {
            if (exception != null)
            {
                exception.Data[LoggedKey] = true;
            }
        }

        /// <summary>
        /// Is this exception logged to the <see cref="InternalLogger"/>?
        /// </summary>
        /// <param name="exception"></param>
        /// <returns><c>true</c>if the <paramref name="exception"/> has been logged to the <see cref="InternalLogger"/>.</returns>
        public static bool IsLoggedToInternalLogger(this Exception exception)
        {
            if (exception?.Data?.Count > 0)
            {
                return exception.Data[LoggedKey] as bool? ?? false;
            }
            return false;
        }

        /// <summary>
        /// Determines whether the exception must be rethrown and logs the error to the <see cref="InternalLogger"/> if <see cref="IsLoggedToInternalLogger"/> is <c>false</c>.
        ///
        /// Advised to log first the error to the <see cref="InternalLogger"/> before calling this method.
        /// </summary>
        /// <param name="exception">The exception to check.</param>
        /// <param name="loggerContext">Target context of the exception.</param>
        /// <returns><c>true</c>if the <paramref name="exception"/> must be rethrown, <c>false</c> otherwise.</returns>
        public static bool MustBeRethrown(this Exception exception, IInternalLoggerContext loggerContext = null)
        {
            if (exception.MustBeRethrownImmediately())
            {
                //no further logging, because it can make severe exceptions only worse.
                return true;
            }

            var isConfigError = exception is NLogConfigurationException;

            //we throw always configuration exceptions (historical)
            if (!exception.IsLoggedToInternalLogger())
            {
                var level = isConfigError ? LogLevel.Warn : LogLevel.Error;
                if (loggerContext != null)
                    InternalLogger.Log(exception, level, "{0}: Error has been raised.", loggerContext);
                else
                    InternalLogger.Log(exception, level, "Error has been raised.");
            }

            //if ThrowConfigExceptions == null, use  ThrowExceptions
            var shallRethrow = isConfigError ? (LogManager.ThrowConfigExceptions ?? LogManager.ThrowExceptions) : LogManager.ThrowExceptions;
            return shallRethrow;
        }

        /// <summary>
        /// Determines whether the exception must be rethrown immediately, without logging the error to the <see cref="InternalLogger"/>.
        ///
        /// Only used this method in special cases.
        /// </summary>
        /// <param name="exception">The exception to check.</param>
        /// <returns><c>true</c>if the <paramref name="exception"/> must be rethrown, <c>false</c> otherwise.</returns>
        public static bool MustBeRethrownImmediately(this Exception exception)
        {
#if !NETSTANDARD1_0
            if (exception is StackOverflowException)
            {
                return true;
            }

            if (exception is ThreadAbortException)
            {
                return true;
            }
#endif

            if (exception is OutOfMemoryException)
            {
                return true;
            }

#if DEBUG
            if (exception is InvalidCastException)
            {
                return true;
            }
            if (exception is NullReferenceException)
            {
                return true;
            }
            if (exception is DivideByZeroException)
            {
                return true;
            }
            if (exception is OverflowException)
            {
                return true;
            }
            if (exception is System.Net.WebException)
            {
                return false;   // Not a real InvalidOperationException
            }
            if (exception is InvalidOperationException)
            {
                return true;    // Ex. Collection was modified
            }
            if (exception is IndexOutOfRangeException)
            {
                return true;
            }
            if (exception is System.Reflection.TargetInvocationException)
            {
                return true;    // Compiler/reflection exception
            }
#endif
            return false;
        }
    }
}

Maybe add LoggingConfiguration as property to `IInternalLoggerContext`, and then extract the LogFactory from that? When InternalLogger-logging is improved with Nlog 5, then it will all work automagically.


@@ -9,7 +9,10 @@ namespace Datadog.Trace.Util
     internal static class DomainMetadata
     {
         private const string UnknownName = "unknown";
-        private static Process _currentProcess;
+        private static bool _initialized;
+        private static string _currentProcessName;
+        private static string _currentProcessMachineName;
+        private static int _currentProcessId;
         private static bool _processDataPoisoned;
         private static bool _domainDataPoisoned;
         private static bool? _isAppInsightsAppDomain;

using System;
using System.Diagnostics;

namespace Datadog.Trace.Util
{
    /// <summary>
    /// Dedicated helper class for consistently referencing Process and AppDomain information.
    /// </summary>
    internal static class DomainMetadata
    {
        private const string UnknownName = "unknown";
        private static Process _currentProcess;
        private static bool _processDataPoisoned;
        private static bool _domainDataPoisoned;
        private static bool? _isAppInsightsAppDomain;

        static DomainMetadata()
        {
            TrySetProcess();
        }

        public static string ProcessName
        {
            get
            {
                try
                {
                    return !_processDataPoisoned ? _currentProcess.ProcessName : UnknownName;
                }
                catch
                {
                    _processDataPoisoned = true;
                    return UnknownName;
                }
            }
        }

        public static string MachineName
        {
            get
            {
                try
                {
                    return !_processDataPoisoned ? _currentProcess.MachineName : UnknownName;
                }
                catch
                {
                    _processDataPoisoned = true;
                    return UnknownName;
                }
            }
        }

        public static int ProcessId
        {
            get
            {
                try
                {
                    return !_processDataPoisoned ? _currentProcess.Id : -1;
                }
                catch
                {
                    _processDataPoisoned = true;
                    return -1;
                }
            }
        }

        public static string AppDomainName
        {
            get
            {
                try
                {
                    return !_domainDataPoisoned ? AppDomain.CurrentDomain.FriendlyName : UnknownName;
                }
                catch
                {
                    _domainDataPoisoned = true;
                    return UnknownName;
                }
            }
        }

        public static int AppDomainId
        {
            get
            {
                try
                {
                    return !_domainDataPoisoned ? AppDomain.CurrentDomain.Id : -1;
                }
                catch
                {
                    _domainDataPoisoned = true;
                    return -1;
                }
            }
        }

        public static bool ShouldAvoidAppDomain()
        {
            if (_isAppInsightsAppDomain == null)
            {
                _isAppInsightsAppDomain = AppDomainName.IndexOf("ApplicationInsights", StringComparison.OrdinalIgnoreCase) >= 0;
            }

            return _isAppInsightsAppDomain.Value;
        }

        private static void TrySetProcess()
        {
            try
            {
                if (!_processDataPoisoned && _currentProcess == null)
                {
                    _currentProcess = Process.GetCurrentProcess();
                }
            }
            catch
            {
                _processDataPoisoned = true;
            }
        }
    }
}

Do we need `_processDataPoisoned`? Can the name or the id of the current process ever change? Or the machine name?


@@ -48,5 +48,20 @@ namespace OpenTelemetry.Exporter.Jaeger
         /// Gets or sets the tags that should be sent with telemetry.
         /// </summary>
         public IEnumerable<KeyValuePair<string, object>> ProcessTags { get; set; }
+
+        /// <summary>
+        /// Gets or sets a value indicating whether or not a batch should be sent to the Jaeger agent for each service. Default value: true.
+        /// </summary>
+        /// <remarks>
+        /// Jaeger UI will only detect & color dependency spans when both
+        /// the client & server processes report data to the same Jaeger
+        /// instance. For processes that make calls to non-instrumented services
+        /// (third parties, SQL, legacy systems, etc.) the
+        /// GenerateServiceSpecificBatches flag is provided to trick Jaeger into
+        /// correctly detecting and displaying all dependent spans as if both
+        /// sides reported data. For more details, see <a
+        /// href="https://github.com/jaegertracing/jaeger-ui/issues/594">jaeger-ui/issues/594</a>.
+        /// </remarks>
+        public bool GenerateServiceSpecificBatches { get; set; } = true;
     }
 }

// <copyright file="JaegerExporterOptions.cs" company="OpenTelemetry Authors">
// Copyright The OpenTelemetry Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// </copyright>

using System.Collections.Generic;

namespace OpenTelemetry.Exporter.Jaeger
{
    public class JaegerExporterOptions
    {
        internal const string DefaultServiceName = "OpenTelemetry Exporter";

        internal const int DefaultMaxPayloadSizeInBytes = 4096;

        /// <summary>
        /// Gets or sets the name of the service reporting telemetry. Default value: OpenTelemetry Exporter.
        /// </summary>
        public string ServiceName { get; set; } = DefaultServiceName;

        /// <summary>
        /// Gets or sets the Jaeger agent host. Default value: localhost.
        /// </summary>
        public string AgentHost { get; set; } = "localhost";

        /// <summary>
        /// Gets or sets the Jaeger agent "compact thrift protocol" port. Default value: 6831.
        /// </summary>
        public int AgentPort { get; set; } = 6831;

        /// <summary>
        /// Gets or sets the maximum payload size in bytes. Default value: 4096.
        /// </summary>
        public int? MaxPayloadSizeInBytes { get; set; } = DefaultMaxPayloadSizeInBytes;

        /// <summary>
        /// Gets or sets the tags that should be sent with telemetry.
        /// </summary>
        public IEnumerable<KeyValuePair<string, object>> ProcessTags { get; set; }
    }
}

Given there is a concern that this causes exporter to send "incorrect" data, should we make this default to "false", so that SDK by default exports correct data. If a user want to send "incorrect" data to have better UI experience, let them explicitly opt-in to this behavior?


@@ -55,7 +55,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.FunctionalTests.Http2
             get
             {
                 var dataset = new TheoryData<H2SpecTestCase>();
-                var toSkip = new[] { "http2/5.1/8" };
+                var toSkip = new string[] { /*"http2/5.1/8"*/ };

                 foreach (var testcase in H2SpecCommands.EnumerateTestCases())
                 {

// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.

#if NETCOREAPP2_2

using System.IO;
using System.Linq;
using System.Net;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Server.Kestrel.Core;
using Microsoft.AspNetCore.Testing;
using Microsoft.AspNetCore.Testing.xunit;
using Xunit;
using Xunit.Abstractions;

namespace Microsoft.AspNetCore.Server.Kestrel.FunctionalTests.Http2
{
    [OSSkipCondition(OperatingSystems.MacOSX, SkipReason = "Missing SslStream ALPN support: https://github.com/dotnet/corefx/issues/30492")]
    [MinimumOSVersion(OperatingSystems.Windows, WindowsVersions.Win81,
        SkipReason = "Missing Windows ALPN support: https://en.wikipedia.org/wiki/Application-Layer_Protocol_Negotiation#Support")]
    public class H2SpecTests : TestApplicationErrorLoggerLoggedTest
    {
        [ConditionalTheory]
        [MemberData(nameof(H2SpecTestCases))]
        public async Task RunIndividualTestCase(H2SpecTestCase testCase)
        {
            var hostBuilder = TransportSelector.GetWebHostBuilder()
                .UseKestrel(options =>
                {
                    options.Listen(IPAddress.Loopback, 0, listenOptions =>
                    {
                        listenOptions.Protocols = HttpProtocols.Http2;
                        if (testCase.Https)
                        {
                            listenOptions.UseHttps(TestResources.TestCertificatePath, "testPassword");
                        }
                    });
                })
                .ConfigureServices(AddTestLogging)
                .Configure(ConfigureHelloWorld);

            using (var host = hostBuilder.Build())
            {
                await host.StartAsync();

                H2SpecCommands.RunTest(testCase.Id, host.GetPort(), testCase.Https, Logger);
            }
        }

        public static TheoryData<H2SpecTestCase> H2SpecTestCases
        {
            get
            {
                var dataset = new TheoryData<H2SpecTestCase>();
                var toSkip = new[] { "http2/5.1/8" };

                foreach (var testcase in H2SpecCommands.EnumerateTestCases())
                {
                    string skip = null;
                    if (toSkip.Contains(testcase.Item1))
                    {
                        skip = "https://github.com/aspnet/KestrelHttpServer/issues/2154";
                    }

                    dataset.Add(new H2SpecTestCase
                    {
                        Id = testcase.Item1,
                        Description = testcase.Item2,
                        Https = false,
                        Skip = skip,
                    });

                    dataset.Add(new H2SpecTestCase
                    {
                        Id = testcase.Item1,
                        Description = testcase.Item2,
                        Https = true,
                        Skip = skip,
                    });
                }

                return dataset;
            }
        }

        public class H2SpecTestCase : IXunitSerializable
        {
            // For the serializer
            public H2SpecTestCase()
            {
            }

            public string Id { get; set; }
            public string Description { get; set; }
            public bool Https { get; set; }
            public string Skip { get; set; }

            public void Deserialize(IXunitSerializationInfo info)
            {
                Id = info.GetValue<string>(nameof(Id));
                Description = info.GetValue<string>(nameof(Description));
                Https = info.GetValue<bool>(nameof(Https));
                Skip = info.GetValue<string>(nameof(Skip));
            }

            public void Serialize(IXunitSerializationInfo info)
            {
                info.AddValue(nameof(Id), Id, typeof(string));
                info.AddValue(nameof(Description), Description, typeof(string));
                info.AddValue(nameof(Https), Https, typeof(bool));
                info.AddValue(nameof(Skip), Skip, typeof(string));
            }

            public override string ToString()
            {
                return $"{Id}, HTTPS:{Https}, {Description}";
            }
        }

        private void ConfigureHelloWorld(IApplicationBuilder app)
        {
            app.Run(async context =>
            {
                // Read the whole request body to check for errors.
                await context.Request.Body.CopyToAsync(Stream.Null);
                await context.Response.WriteAsync("Hello World");
            });
        }
    }
}
#elif NET461 // HTTP/2 is not supported
#else
#error TFMs need updating
#endif


@@ -16,12 +16,13 @@
 //

 using Nethermind.Core;
+using Nethermind.TxPool;

 namespace Nethermind.Consensus.Transactions
 {
     public class NullTxFilter : ITxFilter
     {
-        public (bool Allowed, string Reason) IsAllowed(Transaction tx, BlockHeader parentHeader) => (true, string.Empty);
+        public (bool Allowed, AddTxResult? Reason) IsAllowed(Transaction tx, BlockHeader parentHeader) => (true, null);

         public static readonly NullTxFilter Instance = new();
     }

//  Copyright (c) 2021 Demerzel Solutions Limited
//  This file is part of the Nethermind library.
//
//  The Nethermind library is free software: you can redistribute it and/or modify
//  it under the terms of the GNU Lesser General Public License as published by
//  the Free Software Foundation, either version 3 of the License, or
//  (at your option) any later version.
//
//  The Nethermind library is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
//  GNU Lesser General Public License for more details.
//
//  You should have received a copy of the GNU Lesser General Public License
//  along with the Nethermind. If not, see <http://www.gnu.org/licenses/>.
//

using Nethermind.Core;

namespace Nethermind.Consensus.Transactions
{
    public class NullTxFilter : ITxFilter
    {
        public (bool Allowed, string Reason) IsAllowed(Transaction tx, BlockHeader parentHeader) => (true, string.Empty);

        public static readonly NullTxFilter Instance = new();
    }
}

As we have AddTxResult.Added, we don't need the tuple now, we can simplify this a lot.


@@ -3,14 +3,47 @@
 // See the LICENSE file in the project root for more information.

 using System;
+using Foundation;
 using MvvmCross.Core;
+using MvvmCross.ViewModels;
 using UIKit;

 namespace MvvmCross.Platform.Tvos.Core
 {
-    public class MvxApplicationDelegate : UIApplicationDelegate
-                                          , IMvxApplicationDelegate
+    public abstract class MvxApplicationDelegate : UIApplicationDelegate, IMvxApplicationDelegate
     {
+        private MvxTvosSetup _setup;
+        protected MvxTvosSetup Setup
+        {
+            get
+            {
+                if (_setup == null)
+                    _setup = CreateSetup(this, Window);
+                return _setup;
+            }
+        }
+
+        public override bool FinishedLaunching(UIApplication application, NSDictionary launchOptions)
+        {
+            Setup.Initialize();
+            RunAppStart(launchOptions);
+
+            FireLifetimeChanged(MvxLifetimeEvent.Launching);
+            return base.FinishedLaunching(application, launchOptions);
+        }
+
+        protected virtual void RunAppStart(object hint = null)
+        {
+            var startup = Mvx.Resolve<IMvxAppStart>();
+            if (!startup.IsStarted)
+                startup.Start(GetAppStartHint(hint));
+        }
+
+        protected virtual object GetAppStartHint(object hint = null)
+        {
+            return null;
+        }
+
         public override void WillEnterForeground(UIApplication application)
         {
             FireLifetimeChanged(MvxLifetimeEvent.ActivatedFromMemory);

// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MS-PL license.
// See the LICENSE file in the project root for more information.

using System;
using MvvmCross.Core;
using UIKit;

namespace MvvmCross.Platform.Tvos.Core
{
    public class MvxApplicationDelegate : UIApplicationDelegate
                                          , IMvxApplicationDelegate
    {
        public override void WillEnterForeground(UIApplication application)
        {
            FireLifetimeChanged(MvxLifetimeEvent.ActivatedFromMemory);
        }

        public override void DidEnterBackground(UIApplication application)
        {
            FireLifetimeChanged(MvxLifetimeEvent.Deactivated);
        }

        public override void WillTerminate(UIApplication application)
        {
            FireLifetimeChanged(MvxLifetimeEvent.Closing);
        }

        public override void FinishedLaunching(UIApplication application)
        {
            FireLifetimeChanged(MvxLifetimeEvent.Launching);
        }

        private void FireLifetimeChanged(MvxLifetimeEvent which)
        {
            var handler = LifetimeChanged;
            handler?.Invoke(this, new MvxLifetimeEventArgs(which));
        }

        public event EventHandler<MvxLifetimeEventArgs> LifetimeChanged;
    }
}

Can we make tvOS work the same way as Android and iOS? (use a `InitializePlatform` method instead of ctor arguments) It seems cleaner to me to unify all setup changes on the same PR


@@ -174,6 +174,7 @@ namespace pwiz.Skyline.Model.Results
                     _completed(result, x == null ? _status : _status.ChangeErrorException(x));
                 }
                 catch (Exception x2)
+
                 {
                     _completed(null, _status.ChangeErrorException(x2));
                 }

/*
 * Original author: Brendan MacLean <brendanx .at. u.washington.edu>,
 *                  MacCoss Lab, Department of Genome Sciences, UW
 *
 * Copyright 2009 University of Washington - Seattle, WA
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
using System;
using System.Collections.Generic;
using System.IO;
using pwiz.Common.Collections;
using pwiz.Common.SystemUtil;
using pwiz.Skyline.Properties;
using pwiz.Skyline.Util;
using pwiz.Skyline.Util.Extensions;

namespace pwiz.Skyline.Model.Results
{
    internal class ChromCacheWriter : IDisposable
    {
        private readonly Action<ChromatogramCache, IProgressStatus> _completed;

        protected List<ChromCachedFile> _listCachedFiles = new List<ChromCachedFile>();
        protected BlockedArrayList<ChromTransition> _listTransitions =
            new BlockedArrayList<ChromTransition>(ChromTransition.SizeOf, ChromTransition.DEFAULT_BLOCK_SIZE);
        protected BlockedArrayList<ChromGroupHeaderEntry> _listGroups =
            new BlockedArrayList<ChromGroupHeaderEntry>(ChromGroupHeaderInfo.SizeOf, ChromGroupHeaderInfo.DEFAULT_BLOCK_SIZE);
        protected List<byte> _listTextIdBytes = new List<byte>();
        protected readonly List<Type> _listScoreTypes = new List<Type>();
        protected readonly FileSaver _fs;
        protected readonly FileSaver _fsScans;
        protected readonly FileSaver _fsPeaks;
        protected readonly FileSaver _fsScores;
        protected readonly ILoadMonitor _loader;
        protected IProgressStatus _status;
        protected int _peakCount;
        protected int _scoreCount;
        protected IPooledStream _destinationStream;

        protected ChromCacheWriter(string cachePath, ILoadMonitor loader, IProgressStatus status,
                                   Action<ChromatogramCache, IProgressStatus> completed)
        {
            CachePath = cachePath;
            CacheFormat = CacheFormat.CURRENT;
            _fs = new FileSaver(CachePath);
            _fsScans = new FileSaver(CachePath + ChromatogramCache.SCANS_EXT, true);
            _fsPeaks = new FileSaver(CachePath + ChromatogramCache.PEAKS_EXT, true);
            _fsScores = new FileSaver(CachePath + ChromatogramCache.SCORES_EXT, true);
            _loader = loader;
            _status = status;
            _completed = completed;
        }

        protected string CachePath { get; private set; }

        public CacheFormat CacheFormat { get; protected set; }

        protected void Complete(Exception x)
        {
            lock (this)
            {
                ChromatogramCache result = null;
                try
                {
                    if (x == null && !_status.IsFinal)
                    {
                        long locationScanIds = 0, countBytesScanIds = 0;
                        if (_fs.Stream != null)
                        {
                            try
                            {
                                locationScanIds = _fs.Stream.Position;
                                countBytesScanIds = _fsScans.Stream.Position;

                                _listGroups.Sort();
                                var listChromGroupHeaderInfos = ReadOnlyList.Create(_listGroups.Count,
                                    i => _listGroups[i].ChromGroupHeaderInfo);
                                ChromatogramCache.WriteStructs(CacheFormat,
                                                               _fs.Stream,
                                                               _fsScans.Stream,
                                                               _fsPeaks.Stream,
                                                               _fsScores.Stream,
                                                               _listCachedFiles,
                                                               listChromGroupHeaderInfos,
                                                               _listTransitions,
                                                               _listTextIdBytes,
                                                               _listScoreTypes,
                                                               _scoreCount,
                                                               _peakCount);

                                _loader.StreamManager.Finish(_fs.Stream);
                                _fs.Stream = null;
                                // Allow cancellation right up to the final commit
                                if (!_loader.IsCanceled)
                                    _fs.Commit(_destinationStream);
                                else
                                {
                                    _loader.UpdateProgress(_status = _status.Cancel());
                                }
                            }
                            catch (Exception xWrite)
                            {
                                throw new IOException(TextUtil.LineSeparate(string.Format(Resources.ChromCacheWriter_Complete_Failure_attempting_to_write_the_file__0_, _fs.RealName), xWrite.Message));
                            }
                        }

                        if (!_status.IsCanceled)
                        {
                            // Create stream identifier, but do not open.  The stream will be opened
                            // the first time the document uses it.
                            var readStream = _loader.StreamManager.CreatePooledStream(CachePath, false);

                            // DebugLog.Info("{0}. {1} - created", readStream.GlobalIndex, CachePath);

                            _fsPeaks.Stream.Seek(0, SeekOrigin.Begin);
                            _fsScores.Stream.Seek(0, SeekOrigin.Begin);
                            var arrayCachFiles = _listCachedFiles.ToArray();
                            _listCachedFiles = null;
                            var arrayChromEntries = BlockedArray<ChromGroupHeaderInfo>.Convert(_listGroups,
                                entry => entry.ChromGroupHeaderInfo);
                            _listGroups = null;
                            var arrayTransitions = _listTransitions.ToBlockedArray();
                            _listTransitions = null;
                            var peakSerializer = CacheFormat.ChromPeakSerializer();
                            var chromPeaks = new BlockedArray<ChromPeak>(
                                count => peakSerializer.ReadArray(_fsPeaks.FileStream, count), _peakCount,
                                ChromPeak.SizeOf, ChromPeak.DEFAULT_BLOCK_SIZE);
                            var scores = new BlockedArray<float>(
                                count => PrimitiveArrays.Read<float>(_fsScores.FileStream, count), _scoreCount,
                                sizeof(float), ChromatogramCache.DEFAULT_SCORES_BLOCK_SIZE);
                            var textIdBytes = _listTextIdBytes.ToArray();
                            _listTextIdBytes = null;

                            var rawData = new ChromatogramCache.RawData(CacheFormat)
                            {
                                ChromCacheFiles = arrayCachFiles,
                                ChromatogramEntries = arrayChromEntries,
                                ChromTransitions = arrayTransitions,
                                ChromatogramPeaks = chromPeaks,
                                ScoreTypes = _listScoreTypes.ToArray(),
                                Scores = scores,
                                TextIdBytes = textIdBytes,
                                CountBytesScanIds = countBytesScanIds,
                                LocationScanIds = locationScanIds
                            };
                            result = new ChromatogramCache(CachePath, rawData, readStream);
                            _status = _status.Complete();
                            _loader.UpdateProgress(_status);
                        }
                    }
                }
                catch (Exception x2)
                {
                    x = x2;
                }
                finally
                {
                    Dispose();
                }

                try
                {
                    _completed(result, x == null ? _status : _status.ChangeErrorException(x));
                }
                catch (Exception x2)
                {
                    _completed(null, _status.ChangeErrorException(x2));
                }
            }
        }

        public virtual void Dispose()
        {
            if (_fs.Stream != null)
            {
                try { _loader.StreamManager.Finish(_fs.Stream); }
                catch (IOException) { }
                _fs.Stream = null;
            }
            _fs.Dispose();
            _fsPeaks.Dispose();
            _fsScans.Dispose();
            _fsScores.Dispose();
        }
    }
}


@@ -16,10 +16,16 @@
 //

 using System;
+using System.Collections.Generic;
 using System.IO;
 using System.Linq;
 using System.Reflection;
 using FluentAssertions;
+using Nethermind.Core;
+using Nethermind.Logging;
+using Nethermind.Monitoring.Config;
+using Nethermind.Monitoring.Metrics;
+using Nethermind.Runner;
 using NUnit.Framework;

 namespace Nethermind.Monitoring.Test

//  Copyright (c) 2021 Demerzel Solutions Limited
//  This file is part of the Nethermind library.
//
//  The Nethermind library is free software: you can redistribute it and/or modify
//  it under the terms of the GNU Lesser General Public License as published by
//  the Free Software Foundation, either version 3 of the License, or
//  (at your option) any later version.
//
//  The Nethermind library is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
//  GNU Lesser General Public License for more details.
//
//  You should have received a copy of the GNU Lesser General Public License
//  along with the Nethermind. If not, see <http://www.gnu.org/licenses/>.
//

using System;
using System.IO;
using System.Linq;
using System.Reflection;
using FluentAssertions;
using NUnit.Framework;

namespace Nethermind.Monitoring.Test
{
    [TestFixture]
    public class MetricsTests
    {
        [Test]
        public void All_config_items_have_descriptions()
        {
            ValidateMetricsDescriptions();
        }

        public static void ValidateMetricsDescriptions()
        {
            ForEachProperty(CheckDescribedOrHidden);
        }

        private static void CheckDescribedOrHidden(PropertyInfo property)
        {
            System.ComponentModel.DescriptionAttribute attribute = property.GetCustomAttribute<System.ComponentModel.DescriptionAttribute>();
            attribute.Should().NotBeNull();
        }

        private static void ForEachProperty(Action<PropertyInfo> verifier)
        {
            string[] dlls = Directory.GetFiles(AppDomain.CurrentDomain.BaseDirectory, "Nethermind.*.dll");
            foreach (string dll in dlls)
            {
                TestContext.WriteLine($"Verify {nameof(MetricsTests)} on {Path.GetFileName(dll)}");
                Assembly assembly = Assembly.LoadFile(dll);
                Type[] configs = assembly.GetExportedTypes().Where(t => t.Name == "Metrics").ToArray();

                foreach (Type metricsType in configs)
                {
                    TestContext.WriteLine($"  Verifying type {metricsType.FullName}");
                    PropertyInfo[] properties = metricsType.GetProperties(BindingFlags.Static | BindingFlags.Public);
                    foreach (PropertyInfo property in properties)
                    {
                        try
                        {
                            TestContext.WriteLine($"    Verifying property {property.Name}");
                            verifier(property);
                        }
                        catch (Exception e)
                        {
                            throw new Exception(property.Name, e);
                        }
                    }
                }
            }
        }
    }
}

minor: typo (knowMetricsTypes -> knownMetricsTypes)


@@ -46,13 +46,13 @@ namespace OpenTelemetry.Extensions.Hosting.Implementation
             }
         }

-        [Event(1, Message = "Failed to initialize: '{0}'. OpenTelemetry will not work.", Level = EventLevel.Error)]
+        [Event(1, Message = "An exception occured while adding OpenTelemetry Tracing to ServiceCollection. OpenTelemetry tracing will not work. Exception: '{0}'.", Level = EventLevel.Error)]
         public void FailedInitialize(string exception)
         {
             this.WriteEvent(1, exception);
         }

-        [Event(2, Message = "Failed to get OpenTelemetrySDK: '{0}'. OpenTelemetry will not work.", Level = EventLevel.Error)]
+        [Event(2, Message = "An exception occured while retrieving OpenTelemetry Tracer from Service Provider. OpenTelemetry tracing will not work. Exception: '{0}'.", Level = EventLevel.Error)]
         public void FailedOpenTelemetrySDK(string exception)
         {
             this.WriteEvent(2, exception);

// <copyright file="HostingExtensionsEventSource.cs" company="OpenTelemetry Authors">
// Copyright The OpenTelemetry Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// </copyright>

using System;
using System.Diagnostics.Tracing;
using OpenTelemetry.Internal;

namespace OpenTelemetry.Extensions.Hosting.Implementation
{
    /// <summary>
    /// EventSource events emitted from the project.
    /// </summary>
    [EventSource(Name = "OpenTelemetry-Extensions-Hosting")]
    internal class HostingExtensionsEventSource : EventSource
    {
        public static HostingExtensionsEventSource Log = new HostingExtensionsEventSource();

        [NonEvent]
        public void FailedInitialize(Exception ex)
        {
            if (this.IsEnabled(EventLevel.Error, (EventKeywords)(-1)))
            {
                this.FailedInitialize(ex.ToInvariantString());
            }
        }

        [NonEvent]
        public void FailedOpenTelemetrySDK(Exception ex)
        {
            if (this.IsEnabled(EventLevel.Error, (EventKeywords)(-1)))
            {
                this.FailedOpenTelemetrySDK(ex.ToInvariantString());
            }
        }

        [Event(1, Message = "Failed to initialize: '{0}'. OpenTelemetry will not work.", Level = EventLevel.Error)]
        public void FailedInitialize(string exception)
        {
            this.WriteEvent(1, exception);
        }

        [Event(2, Message = "Failed to get OpenTelemetrySDK: '{0}'. OpenTelemetry will not work.", Level = EventLevel.Error)]
        public void FailedOpenTelemetrySDK(string exception)
        {
            this.WriteEvent(2, exception);
        }
    }
}

Happy to get suggestion for better messaging here. Here's what I intended to convey: Something is wrong - the Exception is a hint to what might be the cause The impact of that - tracing wont work.


@@ -126,6 +126,8 @@ namespace Nethermind.Synchronization.ParallelSync
         }

         public long FindBestHeader() => _blockTree.BestSuggestedHeader?.Number ?? 0;
+
+        public Keccak FindBestHeaderHash() => _blockTree.BestSuggestedHeader?.Hash ?? Keccak.Zero;

         public long FindBestFullBlock() => Math.Min(FindBestHeader(), _blockTree.BestSuggestedBody?.Number ?? 0); // avoiding any potential concurrency issue

//  Copyright (c) 2018 Demerzel Solutions Limited
//  This file is part of the Nethermind library.
//
//  The Nethermind library is free software: you can redistribute it and/or modify
//  it under the terms of the GNU Lesser General Public License as published by
//  the Free Software Foundation, either version 3 of the License, or
//  (at your option) any later version.
//
//  The Nethermind library is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
//  GNU Lesser General Public License for more details.
//
//  You should have received a copy of the GNU Lesser General Public License
//  along with the Nethermind. If not, see <http://www.gnu.org/licenses/>.

using System;
using Nethermind.Blockchain;
using Nethermind.Blockchain.Receipts;
using Nethermind.Blockchain.Synchronization;
using Nethermind.Core;
using Nethermind.Core.Crypto;
using Nethermind.Db;
using Nethermind.Dirichlet.Numerics;
using Nethermind.Logging;

namespace Nethermind.Synchronization.ParallelSync
{
    public class SyncProgressResolver : ISyncProgressResolver
    {
        // TODO: we can search 1024 back and confirm 128 deep header and start using it as Max(0, confirmed)
        // then we will never have to look 128 back again
        // note that we will be doing that every second or so
        private const int _maxLookupBack = 128;

        private readonly IBlockTree _blockTree;
        private readonly IReceiptStorage _receiptStorage;
        private readonly IDb _stateDb;
        private readonly IDb _beamStateDb;
        private readonly ISyncConfig _syncConfig;
        private ILogger _logger;

        public SyncProgressResolver(IBlockTree blockTree, IReceiptStorage receiptStorage, IDb stateDb, IDb beamStateDb, ISyncConfig syncConfig, ILogManager logManager)
        {
            _logger = logManager?.GetClassLogger() ?? throw new ArgumentNullException(nameof(logManager));
            _blockTree = blockTree ?? throw new ArgumentNullException(nameof(blockTree));
            _receiptStorage = receiptStorage ?? throw new ArgumentNullException(nameof(receiptStorage));
            _stateDb = stateDb ?? throw new ArgumentNullException(nameof(stateDb));
            _beamStateDb = beamStateDb ?? throw new ArgumentNullException(nameof(beamStateDb));
            _syncConfig = syncConfig ?? throw new ArgumentNullException(nameof(syncConfig));
        }

        private bool IsFullySynced(Keccak stateRoot)
        {
            if (stateRoot == Keccak.EmptyTreeHash)
            {
                return true;
            }

            return _stateDb.Innermost.Get(stateRoot) != null;
        }

        private bool IsBeamSynced(Keccak stateRoot)
        {
            if (stateRoot == Keccak.EmptyTreeHash)
            {
                return true;
            }

            return _beamStateDb.Innermost.Get(stateRoot) != null;
        }

        public long FindBestFullState()
        {
            // so the full state can be in a few places but there are some best guesses
            // if we are state syncing then the full state may be one of the recent blocks (maybe one of the last 128 blocks)
            // if we full syncing then the state should be at head
            // if we are beam syncing then the state should be in a different DB and should not cause much trouble here
            // it also may seem tricky if best suggested is part of a reorg while we are already full syncing so
            // ideally we would like to check it siblings too (but this may be a bit expensive and less likely
            // to be important
            // we want to avoid a scenario where state is not found even as it is just near head or best suggested

            Block head = _blockTree.Head;
            BlockHeader initialBestSuggested = _blockTree.BestSuggestedHeader; // just storing here for debugging sake
            BlockHeader bestSuggested = initialBestSuggested;

            long bestFullState = 0;
            if (head != null)
            {
                // head search should be very inexpensive as we generally expect the state to be there
                bestFullState = SearchForFullState(head.Header);
            }

            if (bestSuggested != null)
            {
                if (bestFullState < bestSuggested?.Number)
                {
                    bestFullState = Math.Max(bestFullState, SearchForFullState(bestSuggested));
                }
            }

            return bestFullState;
        }

        private long SearchForFullState(BlockHeader startHeader)
        {
            long bestFullState = 0;
            for (int i = 0; i < _maxLookupBack; i++)
            {
                if (startHeader == null)
                {
                    break;
                }

                if (IsFullySynced(startHeader.StateRoot))
                {
                    bestFullState = startHeader.Number;
                    break;
                }

                startHeader = _blockTree.FindHeader(startHeader.ParentHash, BlockTreeLookupOptions.TotalDifficultyNotNeeded);
            }

            return bestFullState;
        }

        public long FindBestHeader() => _blockTree.BestSuggestedHeader?.Number ?? 0;

        public long FindBestFullBlock() => Math.Min(FindBestHeader(), _blockTree.BestSuggestedBody?.Number ?? 0); // avoiding any potential concurrency issue

        public bool IsLoadingBlocksFromDb()
        {
            return !_blockTree.CanAcceptNewBlocks;
        }

        public long FindBestProcessedBlock() => _blockTree.Head?.Number ?? -1;

        public UInt256 ChainDifficulty => _blockTree.BestSuggestedBody?.TotalDifficulty ?? UInt256.Zero;

        public bool IsFastBlocksHeadersFinished() => !IsFastBlocks() || (_blockTree.LowestInsertedHeader?.Number ?? long.MaxValue) <= 1;

        public bool IsFastBlocksBodiesFinished() => !IsFastBlocks() || (!_syncConfig.DownloadBodiesInFastSync || (_blockTree.LowestInsertedBody?.Number ?? long.MaxValue) <= 1);

        public bool IsFastBlocksReceiptsFinished() => !IsFastBlocks() || (!_syncConfig.DownloadReceiptsInFastSync || (_receiptStorage.LowestInsertedReceiptBlock ?? long.MaxValue) <= 1);

        private bool IsFastBlocks()
        {
            bool isFastBlocks = _syncConfig.FastBlocks;

            // if pivot number is 0 then it is equivalent to fast blocks disabled
            if (!isFastBlocks || _syncConfig.PivotNumberParsed == 0L)
            {
                return false;
            }

            bool immediateBeamSync = !_syncConfig.DownloadHeadersInFastSync;
            bool anyHeaderDownloaded = _blockTree.LowestInsertedHeader != null;
            if (immediateBeamSync && anyHeaderDownloaded)
            {
                return false;
            }

            return true;
        }

    }
}

Keccak.Zero should not be used to mean null


@@ -47,13 +47,22 @@ namespace OpenTelemetry.Logs
             {
                 var options = this.provider.Options;

+                string formattedMessage = null;
+                if (options.IncludeFormattedMessage)
+                {
+                    if (formatter != null)
+                    {
+                        formattedMessage = formatter(state, exception);
+                    }
+                }
+
                 var record = new LogRecord(
                     options.IncludeScopes ? this.ScopeProvider : null,
                     DateTime.UtcNow,
                     this.categoryName,
                     logLevel,
                     eventId,
-                    options.IncludeFormattedMessage ? formatter(state, exception) : null,
+                    formattedMessage,
                     options.ParseStateValues ? null : (object)state,
                     exception,
                     options.ParseStateValues ? this.ParseState(state) : null);

// <copyright file="OpenTelemetryLogger.cs" company="OpenTelemetry Authors">
// Copyright The OpenTelemetry Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// </copyright>

using System;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
using Microsoft.Extensions.Logging;

namespace OpenTelemetry.Logs
{
    internal class OpenTelemetryLogger : ILogger
    {
        private readonly string categoryName;
        private readonly OpenTelemetryLoggerProvider provider;

        internal OpenTelemetryLogger(string categoryName, OpenTelemetryLoggerProvider provider)
        {
            this.categoryName = categoryName ?? throw new ArgumentNullException(nameof(categoryName));
            this.provider = provider ?? throw new ArgumentNullException(nameof(provider));
        }

        internal IExternalScopeProvider ScopeProvider { get; set; }

        public void Log<TState>(LogLevel logLevel, EventId eventId, TState state, Exception exception, Func<TState, Exception, string> formatter)
        {
            if (!this.IsEnabled(logLevel)
                || Sdk.SuppressInstrumentation)
            {
                return;
            }

            var processor = this.provider.Processor;
            if (processor != null)
            {
                var options = this.provider.Options;

                var record = new LogRecord(
                    options.IncludeScopes ? this.ScopeProvider : null,
                    DateTime.UtcNow,
                    this.categoryName,
                    logLevel,
                    eventId,
                    options.IncludeFormattedMessage ? formatter(state, exception) : null,
                    options.ParseStateValues ? null : (object)state,
                    exception,
                    options.ParseStateValues ? this.ParseState(state) : null);

                processor.OnEnd(record);

                record.ScopeProvider = null;
            }
        }

        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public bool IsEnabled(LogLevel logLevel)
        {
            return logLevel != LogLevel.None;
        }

        public IDisposable BeginScope<TState>(TState state) => this.ScopeProvider?.Push(state) ?? null;

        private IReadOnlyList<KeyValuePair<string, object>> ParseState<TState>(TState state)
        {
            if (state is IReadOnlyList<KeyValuePair<string, object>> stateList)
            {
                return stateList;
            }
            else if (state is IEnumerable<KeyValuePair<string, object>> stateValues)
            {
                return new List<KeyValuePair<string, object>>(stateValues);
            }
            else
            {
                return new List<KeyValuePair<string, object>>
                {
                    new KeyValuePair<string, object>(string.Empty, state),
                };
            }
        }
    }
}

Could probably just do: `options.IncludeFormattedMessage ? formatter?.Invoke(state, exception) : null`


@@ -53,7 +53,34 @@ namespace pwiz.Common.Chemistry
             {"Thr",'T'},
             {"Trp",'W'},
             {"Tyr",'Y'},
-            {"Val",'V'}
+            {"Val",'V'},
+            {"Sec",'U'},
+            {"Pyl",'O'}
+        });
+        public static readonly IDictionary<char, String> FullNames = new ImmutableDictionary<char, String>(
+            new Dictionary<char, string> {
+            {'A',"Alanine"},
+            {'R', "Arginine"},
+            {'N', "Asparagine"},
+            {'D', "Aspartic acid"},
+            {'C', "Cysteine"},
+            {'E', "Glutamic acid"},
+            {'Q', "Glutamine"},
+            {'G', "Glycine"},
+            {'H', "Histidine"},
+            {'I', "Isoleucine"},
+            {'L', "Leucine"},
+            {'K', "Lysine"},
+            {'M', "Methionine"},
+            {'F', "Phenylalanine"},
+            {'P', "Proline"},
+            {'S', "Serine"},
+            {'T', "Threonine"},
+            {'W', "Tryptophan"},
+            {'Y', "Tyrosine"},
+            {'V', "Valine"},
+            {'U', "Selenocysteine"},
+            {'O', "Pyrrolysine"}
         });
         // ReSharper restore LocalizableElement

/*
 * Original author: Nicholas Shulman <nicksh .at. u.washington.edu>,
 *                  MacCoss Lab, Department of Genome Sciences, UW
 *
 * Copyright 2009 University of Washington - Seattle, WA
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
using System;
using System.Collections.Generic;
using System.Linq;
using JetBrains.Annotations;
using pwiz.Common.Collections;
using pwiz.Common.SystemUtil;

namespace pwiz.Common.Chemistry
{
    public class AminoAcidFormulas : Immutable
    {
// ReSharper disable InconsistentNaming
        // public const double ProtonMass = 1.007276466879;  // per http://physics.nist.gov/cgi-bin/cuu/Value?mpu|search_for=proton+mass 12/18/2016
        public const double ProtonMass = 1.00727649;

        // ReSharper disable LocalizableElement
        public static readonly IDictionary<String, char> LongNames = new ImmutableDictionary<String,char>(
            new Dictionary<string, char> {
            {"Ala",'A'},
            {"Arg",'R'},
            {"Asn",'N'},
            {"Asp",'D'},
            {"Cys",'C'},
            {"Glu",'E'},
            {"Gln",'Q'},
            {"Gly",'G'},
            {"His",'H'},
            {"Ile",'I'},
            {"Leu",'L'},
            {"Lys",'K'},
            {"Met",'M'},
            {"Phe",'F'},
            {"Pro",'P'},
            {"Ser",'S'},
            {"Thr",'T'},
            {"Trp",'W'},
            {"Tyr",'Y'},
            {"Val",'V'}
        });
        // ReSharper restore LocalizableElement

        // ReSharper disable LocalizableElement
        public static readonly IDictionary<char, String> DefaultFormulas = new ImmutableDictionary<char, String>
            (
            new Dictionary<char, string>
                {
                    {'A', "C3H5ON"},
                    {'C', "C3H5ONS"},
                    {'D', "C4H5O3N"},
                    {'E', "C5H7O3N"},
                    {'F', "C9H9ON"},
                    {'G', "C2H3ON"},
                    {'H', "C6H7ON3"},
                    {'I', "C6H11ON"},
                    {'K', "C6H12ON2"},
                    {'L', "C6H11ON"},
                    {'M', "C5H9ONS"},
                    {'N', "C4H6O2N2"},
                    {'O', "C12H19N3O2"},
                    {'P', "C5H7ON"},
                    {'Q', "C5H8O2N2"},
                    {'R', "C6H12ON4"},
                    {'S', "C3H5O2N"},
                    {'T', "C4H7O2N"},
                    {'U', "C3H5NOSe"},
                    {'V', "C5H9ON"},
                    {'W', "C11H10ON2"},
                    {'Y', "C9H9O2N"},
                }
                );
        // ReSharper restore LocalizableElement

        private Dictionary<char, Molecule> _molecules;
        private static readonly Molecule H2O = Molecule.Parse(@"H2O");

        public static readonly AminoAcidFormulas Default = new AminoAcidFormulas
                                                               {
                                                                   MassShifts = new ImmutableDictionary<char,double>(new Dictionary<char, double>()),
                                                                   _molecules = DefaultFormulas.ToDictionary(kvp=>kvp.Key, kvp=>Molecule.Parse(kvp.Value)),
                                                                   IsotopeAbundances = IsotopeAbundances.Default,
                                                                   MassResolution = .001,
                                                               };
// ReSharper restore InconsistentNaming

        public double MassResolution { get; private set; }
        public IDictionary<char, double> MassShifts { get; private set; }
        public IsotopeAbundances IsotopeAbundances { get; private set; }
        public AminoAcidFormulas SetFormula(char aminoAcid, String formula)
        {
            return ChangeProp(ImClone(this), im =>
            {
                im._molecules = new Dictionary<char, Molecule>(_molecules);
                im._molecules[aminoAcid] = Molecule.Parse(formula);
            });
        }
        public AminoAcidFormulas SetMassShift(char aminoAcid, double massShift)
        {
            return SetMassShifts(new Dictionary<char, double> {{aminoAcid, massShift}});
        }
        public AminoAcidFormulas SetMassShifts(Dictionary<char,double> dictionary)
        {
            var newMassShifts = new Dictionary<char, double>(MassShifts);
            foreach (var entry in dictionary)
            {
                newMassShifts[entry.Key] = entry.Value;
            }

            return ChangeProp(ImClone(this), im => im.MassShifts = newMassShifts);
        }
        public AminoAcidFormulas SetIsotopeAbundances(IsotopeAbundances newAbundances)
        {
            return ChangeProp(ImClone(this), im => im.IsotopeAbundances = newAbundances);
        }
        public MassDistribution GetMassDistribution(Molecule molecule, int charge)
        {
            var md = new MassDistribution(MassResolution, .00001);
            var result = md;
            foreach (var element in molecule)
            {
                result = result.Add(md.Add(IsotopeAbundances[element.Key]).Multiply(element.Value));
            }
            if (charge != 0)
            {
                result = result.OffsetAndDivide(charge * ProtonMass, charge);
            }
            return result;
        }
        public AminoAcidFormulas SetMassResolution(double massResolution)
        {
            return ChangeProp(ImClone(this), im=>im.MassResolution = massResolution);
        }
        public MassDistribution GetMassDistribution(String peptide, int charge)
        {
            return GetMassDistribution(GetFormula(peptide), charge)
                .OffsetAndDivide(GetMassShift(peptide)/Math.Max(charge,1), 1);
        }
        public Molecule GetFormula(String peptide)
        {
            var formulas = peptide.Select(aa =>
                _molecules.TryGetValue(aa, out Molecule aaFormula) ? aaFormula : Molecule.Empty
            ).Append(H2O);
            return Molecule.Sum(formulas);
        }

        [CanBeNull]
        public Molecule GetAminoAcidFormula(char aa)
        {
            Molecule molecule;
            _molecules.TryGetValue(aa, out molecule);
            return molecule;
        }

        public Double GetMassShift(String peptide)
        {
            var result = 0.0;
            foreach (var ch in peptide)
            {
                double shift;
                MassShifts.TryGetValue(ch, out shift);
                result += shift;
            }
            return result;
        }
        public double GetMonoisotopicMass(String peptide)
        {
            double result = GetMassShift(peptide);
            foreach (var element in GetFormula(peptide))
            {
                result += IsotopeAbundances[element.Key].MostAbundanceMass*element.Value;
            }
            return result;
        }
    }
}

You should also add these new amino acids to "DefaultFormulas"


@@ -40,7 +40,9 @@ namespace Nethermind.Runner
             ContractResolver = new CamelCasePropertyNamesContractResolver()
         };

-        private IJsonSerializer _jsonSerializer = new EthereumJsonSerializer();
+        private IJsonSerializer _jsonSerializer = CreateJsonSerializer();
+
+        private static EthereumJsonSerializer CreateJsonSerializer() => new EthereumJsonSerializer(NullValueHandling.Include);

         public void ConfigureServices(IServiceCollection services)
         {

//  Copyright (c) 2018 Demerzel Solutions Limited
//  This file is part of the Nethermind library.
//
//  The Nethermind library is free software: you can redistribute it and/or modify
//  it under the terms of the GNU Lesser General Public License as published by
//  the Free Software Foundation, either version 3 of the License, or
//  (at your option) any later version.
//
//  The Nethermind library is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
//  GNU Lesser General Public License for more details.
//
//  You should have received a copy of the GNU Lesser General Public License
//  along with the Nethermind. If not, see <http://www.gnu.org/licenses/>.

using System;
using System.IO;
using System.Text;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Server.Kestrel.Core;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Nethermind.Config;
using Nethermind.Core.Attributes;
using Nethermind.JsonRpc;
using Nethermind.Serialization.Json;
using Nethermind.WebSockets;
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;

namespace Nethermind.Runner
{
    public class Startup
    {
        private static readonly JsonSerializerSettings JsonSettings = new JsonSerializerSettings
        {
            ContractResolver = new CamelCasePropertyNamesContractResolver()
        };

        private IJsonSerializer _jsonSerializer = new EthereumJsonSerializer();

        public void ConfigureServices(IServiceCollection services)
        {
            services.Configure<KestrelServerOptions>(options => { options.AllowSynchronousIO = true; });
            Bootstrap.Instance.RegisterJsonRpcServices(services);
            var corsOrigins = Environment.GetEnvironmentVariable("NETHERMIND_CORS_ORIGINS") ?? "*";
            services.AddCors(c => c.AddPolicy("Cors",
                p => p.AllowAnyMethod().AllowAnyHeader().WithOrigins(corsOrigins)));
        }

        [Todo(Improve.Performance, "Can we write immediately to the stream instead of calling ToString on the entire JSON content?")]
        public void Configure(IApplicationBuilder app, IWebHostEnvironment env, IJsonRpcProcessor jsonRpcProcessor,
            IJsonRpcService jsonRpcService)
        {
            _jsonSerializer = new EthereumJsonSerializer();
            foreach (JsonConverter converter in jsonRpcService.Converters)
            {
                _jsonSerializer.RegisterConverter(converter);
            }

            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }

            app.UseCors("Cors");

            var configProvider = app.ApplicationServices.GetService<IConfigProvider>();
            var initConfig = configProvider.GetConfig<IInitConfig>();
            var jsonRpcConfig = configProvider.GetConfig<IJsonRpcConfig>();
            if (initConfig.WebSocketsEnabled)
            {
                app.UseWebSockets();
                app.UseWhen(ctx => ctx.WebSockets.IsWebSocketRequest
                                   && ctx.Connection.LocalPort == jsonRpcConfig.WebSocketsPort,
                builder => builder.UseWebSocketsModules());
            }

            app.Use(async (ctx, next) =>
            {
                if (ctx.Request.Method == "GET")
                {
                    await ctx.Response.WriteAsync("Nethermind JSON RPC");
                }
                else if (ctx.Connection.LocalPort == jsonRpcConfig.Port && ctx.Request.Method == "POST")
                {
                    using var reader = new StreamReader(ctx.Request.Body, Encoding.UTF8);
                    var request = await reader.ReadToEndAsync();
                    var result = await jsonRpcProcessor.ProcessAsync(request);

                    if (result.IsCollection)
                    {
                        _jsonSerializer.Serialize(ctx.Response.Body, result.Responses);
                    }
                    else
                    {
                        _jsonSerializer.Serialize(ctx.Response.Body, result.Response);
                    }

                    await ctx.Response.CompleteAsync();
                }
            });
        }
    }
}

this cannot be this way - there are plenty of places where they complain about nulls - it has to be done specifically on some properties only


@@ -52,6 +52,8 @@ namespace Nethermind.Runner.Ethereum.Steps

                 JsonRpcService jsonRpcService = new(_api.RpcModuleProvider, _api.LogManager);

+                _api.EthereumJsonSerializer.RegisterConverters(jsonRpcService.Converters);
+
                 JsonRpcProcessor jsonRpcProcessor = new(
                     jsonRpcService,
                     _api.EthereumJsonSerializer,

//  Copyright (c) 2021 Demerzel Solutions Limited
//  This file is part of the Nethermind library.
//
//  The Nethermind library is free software: you can redistribute it and/or modify
//  it under the terms of the GNU Lesser General Public License as published by
//  the Free Software Foundation, either version 3 of the License, or
//  (at your option) any later version.
//
//  The Nethermind library is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
//  GNU Lesser General Public License for more details.
//
//  You should have received a copy of the GNU Lesser General Public License
//  along with the Nethermind. If not, see <http://www.gnu.org/licenses/>.
//

using System.Threading;
using System.Threading.Tasks;
using Nethermind.Api;
using Nethermind.Core;
using Nethermind.Init.Steps;
using Nethermind.JsonRpc;
using Nethermind.JsonRpc.WebSockets;
using Nethermind.Logging;
using Nethermind.Runner.JsonRpc;

namespace Nethermind.Runner.Ethereum.Steps
{
    [RunnerStepDependencies(typeof(InitializeNetwork), typeof(RegisterRpcModules), typeof(SetupHive))]
    public class StartRpc : IStep
    {
        private readonly INethermindApi _api;

        public StartRpc(INethermindApi api)
        {
            _api = api;
        }

        public async Task Execute(CancellationToken cancellationToken)
        {
            IJsonRpcConfig jsonRpcConfig = _api.Config<IJsonRpcConfig>();
            ILogger logger = _api.LogManager.GetClassLogger();

            if (jsonRpcConfig.Enabled)
            {
                IInitConfig initConfig = _api.Config<IInitConfig>();
                JsonRpcLocalStats jsonRpcLocalStats = new(
                    _api.Timestamper,
                    jsonRpcConfig,
                    _api.LogManager);

                JsonRpcService jsonRpcService = new(_api.RpcModuleProvider, _api.LogManager);

                JsonRpcProcessor jsonRpcProcessor = new(
                    jsonRpcService,
                    _api.EthereumJsonSerializer,
                    jsonRpcConfig,
                    _api.FileSystem,
                    _api.LogManager);

                if (initConfig.WebSocketsEnabled)
                {
                    JsonRpcWebSocketsModule webSocketsModule = new (jsonRpcProcessor, jsonRpcService, jsonRpcLocalStats, _api.LogManager, _api.EthereumJsonSerializer);
                    _api.WebSocketsManager!.AddModule(webSocketsModule, true);
                }

                Bootstrap.Instance.JsonRpcService = jsonRpcService;
                Bootstrap.Instance.LogManager = _api.LogManager;
                Bootstrap.Instance.JsonSerializer = _api.EthereumJsonSerializer;
                Bootstrap.Instance.JsonRpcLocalStats = jsonRpcLocalStats;
                JsonRpcRunner? jsonRpcRunner = new(
                    jsonRpcProcessor,
                    _api.WebSocketsManager!,
                    _api.ConfigProvider,
                    _api.LogManager,
                    _api);

                await jsonRpcRunner.Start(cancellationToken).ContinueWith(x =>
                {
                    if (x.IsFaulted && logger.IsError)
                        logger.Error("Error during jsonRpc runner start", x.Exception);
                }, cancellationToken);

                JsonRpcIpcRunner jsonIpcRunner = new(jsonRpcProcessor, jsonRpcService, _api.ConfigProvider, _api.LogManager, jsonRpcLocalStats, _api.EthereumJsonSerializer, _api.FileSystem);
                jsonIpcRunner.Start(cancellationToken);

#pragma warning disable 4014
                _api.DisposeStack.Push(new Reactive.AnonymousDisposable(() => jsonRpcRunner.StopAsync())); // do not await
                _api.DisposeStack.Push(jsonIpcRunner); // do not await
#pragma warning restore 4014
            }
            else
            {
                if (logger.IsInfo) logger.Info("Json RPC is disabled");
            }
        }
    }
}

This change will register JSON RPC converters for the API serializer that is used in multiple places. Is it OK ? HTTP JSON RPC uses own instance of the serializer. Maybe we should do the same for the sockets or share the same instance with the HTTP module ?


@@ -12,8 +12,8 @@
 #include <nano/rpc/rpc_secure.hpp>
 #endif

-nano::rpc::rpc (boost::asio::io_context & io_ctx_a, nano::rpc_config const & config_a, nano::rpc_handler_interface & rpc_handler_interface_a) :
-	config (config_a),
+nano::rpc::rpc (boost::asio::io_context & io_ctx_a, nano::rpc_config config_a, nano::rpc_handler_interface & rpc_handler_interface_a) :
+	config (std::move (config_a)),
 	acceptor (io_ctx_a),
 	logger (std::chrono::milliseconds (0)),
 	io_ctx (io_ctx_a),

#include <nano/boost/asio/bind_executor.hpp>
#include <nano/lib/rpc_handler_interface.hpp>
#include <nano/lib/tlsconfig.hpp>
#include <nano/rpc/rpc.hpp>
#include <nano/rpc/rpc_connection.hpp>

#include <boost/format.hpp>

#include <iostream>

#ifdef NANO_SECURE_RPC
#include <nano/rpc/rpc_secure.hpp>
#endif

nano::rpc::rpc (boost::asio::io_context & io_ctx_a, nano::rpc_config const & config_a, nano::rpc_handler_interface & rpc_handler_interface_a) :
	config (config_a),
	acceptor (io_ctx_a),
	logger (std::chrono::milliseconds (0)),
	io_ctx (io_ctx_a),
	rpc_handler_interface (rpc_handler_interface_a)
{
	rpc_handler_interface.rpc_instance (*this);
}

nano::rpc::~rpc ()
{
	if (!stopped)
	{
		stop ();
	}
}

void nano::rpc::start ()
{
	auto endpoint (boost::asio::ip::tcp::endpoint (boost::asio::ip::make_address_v6 (config.address), config.port));
	bool const is_loopback = (endpoint.address ().is_loopback () || (endpoint.address ().to_v6 ().is_v4_mapped () && boost::asio::ip::make_address_v4 (boost::asio::ip::v4_mapped, endpoint.address ().to_v6 ()).is_loopback ()));
	if (!is_loopback && config.enable_control)
	{
		auto warning = boost::str (boost::format ("WARNING: control-level RPCs are enabled on non-local address %1%, potentially allowing wallet access outside local computer") % endpoint.address ().to_string ());
		std::cout << warning << std::endl;
		logger.always_log (warning);
	}
	acceptor.open (endpoint.protocol ());
	acceptor.set_option (boost::asio::ip::tcp::acceptor::reuse_address (true));

	boost::system::error_code ec;
	acceptor.bind (endpoint, ec);
	if (ec)
	{
		logger.always_log (boost::str (boost::format ("Error while binding for RPC on port %1%: %2%") % endpoint.port () % ec.message ()));
		throw std::runtime_error (ec.message ());
	}
	acceptor.listen ();
	accept ();
}

void nano::rpc::accept ()
{
	auto connection (std::make_shared<nano::rpc_connection> (config, io_ctx, logger, rpc_handler_interface));
	acceptor.async_accept (connection->socket, boost::asio::bind_executor (connection->strand, [this, connection] (boost::system::error_code const & ec) {
		if (ec != boost::asio::error::operation_aborted && acceptor.is_open ())
		{
			accept ();
		}
		if (!ec)
		{
			connection->parse_connection ();
		}
		else
		{
			logger.always_log (boost::str (boost::format ("Error accepting RPC connections: %1% (%2%)") % ec.message () % ec.value ()));
		}
	}));
}

void nano::rpc::stop ()
{
	stopped = true;
	acceptor.close ();
}

std::unique_ptr<nano::rpc> nano::get_rpc (boost::asio::io_context & io_ctx_a, nano::rpc_config const & config_a, nano::rpc_handler_interface & rpc_handler_interface_a)
{
	std::unique_ptr<rpc> impl;

	if (config_a.tls_config && config_a.tls_config->enable_https)
	{
#ifdef NANO_SECURE_RPC
		impl = std::make_unique<rpc_secure> (io_ctx_a, config_a, rpc_handler_interface_a);
#endif
	}
	else
	{
		impl = std::make_unique<rpc> (io_ctx_a, config_a, rpc_handler_interface_a);
	}

	return impl;
}

Is there a reason to change this to pass by value instead of const ref? I changed it back and everything still compiles and runs.


@@ -42,6 +42,7 @@ class named_mutex;
 #include "../plugins/nearest.hpp"
 #include "../plugins/timestamp.hpp"
 #include "../plugins/viaroute.hpp"
+#include "../plugins/map_matching.hpp"
 #include "../server/data_structures/datafacade_base.hpp"
 #include "../server/data_structures/internal_datafacade.hpp"
 #include "../server/data_structures/shared_barriers.hpp"

/*

Copyright (c) 2015, Project OSRM contributors
All rights reserved.

Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:

Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

*/

namespace boost
{
namespace interprocess
{
class named_mutex;
}
}

#include "osrm_impl.hpp"
#include "osrm.hpp"

#include "../plugins/distance_table.hpp"
#include "../plugins/hello_world.hpp"
#include "../plugins/locate.hpp"
#include "../plugins/nearest.hpp"
#include "../plugins/timestamp.hpp"
#include "../plugins/viaroute.hpp"
#include "../server/data_structures/datafacade_base.hpp"
#include "../server/data_structures/internal_datafacade.hpp"
#include "../server/data_structures/shared_barriers.hpp"
#include "../server/data_structures/shared_datafacade.hpp"
#include "../util/make_unique.hpp"
#include "../util/routed_options.hpp"
#include "../util/simple_logger.hpp"

#include <boost/assert.hpp>
#include <boost/interprocess/sync/named_condition.hpp>
#include <boost/interprocess/sync/scoped_lock.hpp>

#include <osrm/route_parameters.hpp>

#include <algorithm>
#include <fstream>
#include <utility>
#include <vector>

OSRM_impl::OSRM_impl(libosrm_config &lib_config)
{
    if (lib_config.use_shared_memory)
    {
        barrier = osrm::make_unique<SharedBarriers>();
        query_data_facade = new SharedDataFacade<QueryEdge::EdgeData>();
    }
    else
    {
        // populate base path
        populate_base_path(lib_config.server_paths);
        query_data_facade = new InternalDataFacade<QueryEdge::EdgeData>(lib_config.server_paths);
    }

    // The following plugins handle all requests.
    RegisterPlugin(new DistanceTablePlugin<BaseDataFacade<QueryEdge::EdgeData>>(
        query_data_facade, lib_config.max_locations_distance_table));
    RegisterPlugin(new HelloWorldPlugin());
    RegisterPlugin(new LocatePlugin<BaseDataFacade<QueryEdge::EdgeData>>(query_data_facade));
    RegisterPlugin(new NearestPlugin<BaseDataFacade<QueryEdge::EdgeData>>(query_data_facade));
    RegisterPlugin(new TimestampPlugin<BaseDataFacade<QueryEdge::EdgeData>>(query_data_facade));
    RegisterPlugin(new ViaRoutePlugin<BaseDataFacade<QueryEdge::EdgeData>>(query_data_facade));
}

OSRM_impl::~OSRM_impl()
{
    delete query_data_facade;
    for (PluginMap::value_type &plugin_pointer : plugin_map)
    {
        delete plugin_pointer.second;
    }
}

void OSRM_impl::RegisterPlugin(BasePlugin *plugin)
{
    SimpleLogger().Write() << "loaded plugin: " << plugin->GetDescriptor();
    if (plugin_map.find(plugin->GetDescriptor()) != plugin_map.end())
    {
        delete plugin_map.find(plugin->GetDescriptor())->second;
    }
    plugin_map.emplace(plugin->GetDescriptor(), plugin);
}

int OSRM_impl::RunQuery(RouteParameters &route_parameters, osrm::json::Object &json_result)
{
    const auto &plugin_iterator = plugin_map.find(route_parameters.service);

    if (plugin_map.end() == plugin_iterator)
    {
        return 400;
    }

    increase_concurrent_query_count();
    plugin_iterator->second->HandleRequest(route_parameters, json_result);
    decrease_concurrent_query_count();
    return 200;
}

// decrease number of concurrent queries
void OSRM_impl::decrease_concurrent_query_count()
{
    if (!barrier)
    {
        return;
    }
    // lock query
    boost::interprocess::scoped_lock<boost::interprocess::named_mutex> query_lock(
        barrier->query_mutex);

    // decrement query count
    --(barrier->number_of_queries);
    BOOST_ASSERT_MSG(0 <= barrier->number_of_queries, "invalid number of queries");

    // notify all processes that were waiting for this condition
    if (0 == barrier->number_of_queries)
    {
        barrier->no_running_queries_condition.notify_all();
    }
}

// increase number of concurrent queries
void OSRM_impl::increase_concurrent_query_count()
{
    if (!barrier)
    {
        return;
    }

    // lock update pending
    boost::interprocess::scoped_lock<boost::interprocess::named_mutex> pending_lock(
        barrier->pending_update_mutex);

    // lock query
    boost::interprocess::scoped_lock<boost::interprocess::named_mutex> query_lock(
        barrier->query_mutex);

    // unlock update pending
    pending_lock.unlock();

    // increment query count
    ++(barrier->number_of_queries);

    (static_cast<SharedDataFacade<QueryEdge::EdgeData> *>(query_data_facade))
        ->CheckAndReloadFacade();
}

// proxy code for compilation firewall
OSRM::OSRM(libosrm_config &lib_config) : OSRM_pimpl_(osrm::make_unique<OSRM_impl>(lib_config)) {}

OSRM::~OSRM() { OSRM_pimpl_.reset(); }

int OSRM::RunQuery(RouteParameters &route_parameters, osrm::json::Object &json_result)
{
    return OSRM_pimpl_->RunQuery(route_parameters, json_result);
}

reorder includes to be alphabetically ordered


@@ -34,6 +34,11 @@ public:
     static constexpr std::int64_t column_count = 2;
     static constexpr std::int64_t element_count = row_count * column_count;

+    bool not_available_on_device() {
+        constexpr bool is_svd = std::is_same_v<Method, pca::method::svd>;
+        return get_policy().is_gpu() && is_svd;
+    }
+
     auto get_descriptor() const {
         return pca::descriptor<float, Method, pca::task::dim_reduction>{};
     }

/*******************************************************************************
* Copyright 2020-2021 Intel Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*     http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*******************************************************************************/

#include <array>

#include "oneapi/dal/algo/pca/infer.hpp"
#include "oneapi/dal/algo/pca/train.hpp"
#include "oneapi/dal/table/row_accessor.hpp"

#include "oneapi/dal/test/engine/common.hpp"
#include "oneapi/dal/test/engine/fixtures.hpp"

namespace oneapi::dal::pca::test {

namespace te = dal::test::engine;

template <typename Method>
class pca_badarg_test : public te::algo_fixture {
public:
    static constexpr std::int64_t row_count = 8;
    static constexpr std::int64_t column_count = 2;
    static constexpr std::int64_t element_count = row_count * column_count;

    auto get_descriptor() const {
        return pca::descriptor<float, Method, pca::task::dim_reduction>{};
    }

    table get_train_data(std::int64_t override_row_count = row_count,
                         std::int64_t override_column_count = column_count) const {
        ONEDAL_ASSERT(override_row_count * override_column_count <= element_count);
        return homogen_table::wrap(train_data_.data(), override_row_count, override_column_count);
    }

    table get_infer_data(std::int64_t override_row_count = row_count,
                         std::int64_t override_column_count = column_count) const {
        ONEDAL_ASSERT(override_row_count * override_column_count <= element_count);
        return homogen_table::wrap(infer_data_.data(), override_row_count, override_column_count);
    }

private:
    static constexpr std::array<float, element_count> train_data_ = {
        1.0, 1.0, 2.0, 2.0, 1.0, 2.0, 2.0, 1.0, -1.0, -1.0, -1.0, -2.0, -2.0, -1.0, -2.0, -2.0
    };

    static constexpr std::array<float, element_count> infer_data_ = {
        1.0, 1.0, 2.0, 2.0, 1.0, 2.0, 2.0, 1.0, -1.0, -1.0, -1.0, -2.0, -2.0, -1.0, -2.0, -2.0
    };
};

#define PCA_BADARG_TEST(name) \
    TEMPLATE_TEST_M(pca_badarg_test, name, "[pca][badarg]", pca::method::cov, pca::method::svd)

PCA_BADARG_TEST("accepts non-negative component_count") {
    REQUIRE_NOTHROW(this->get_descriptor().set_component_count(0));
}

PCA_BADARG_TEST("throws if component_count is negative") {
    REQUIRE_THROWS_AS(this->get_descriptor().set_component_count(-1), domain_error);
}

PCA_BADARG_TEST("throws if train data is empty") {
    const auto pca_desc = this->get_descriptor().set_component_count(2);

    REQUIRE_THROWS_AS(this->train(pca_desc, homogen_table{}), domain_error);
}

PCA_BADARG_TEST("throws if train data columns less than component count") {
    const auto pca_desc = this->get_descriptor().set_component_count(4);

    REQUIRE_THROWS_AS(this->train(pca_desc, this->get_train_data()), invalid_argument);
}

PCA_BADARG_TEST("throws if infer data is empty") {
    const auto pca_desc = this->get_descriptor().set_component_count(2);
    const auto model = this->train(pca_desc, this->get_train_data()).get_model();

    REQUIRE_THROWS_AS(this->infer(pca_desc, model, homogen_table{}), domain_error);
}

PCA_BADARG_TEST("throws if component count neq eigenvector_rows") {
    auto pca_desc = this->get_descriptor().set_component_count(2);
    const auto model = this->train(pca_desc, this->get_train_data()).get_model();
    pca_desc.set_component_count(4);

    REQUIRE_THROWS_AS(this->infer(pca_desc, model, this->get_infer_data()), invalid_argument);
}

PCA_BADARG_TEST("throws if infer data column count neq eigenvector columns") {
    const auto pca_desc = this->get_descriptor().set_component_count(2);
    const auto model = this->train(pca_desc, this->get_train_data()).get_model();
    const auto infer_data = this->get_infer_data(4, 4);

    REQUIRE_THROWS_AS(this->infer(pca_desc, model, infer_data), invalid_argument);
}

} // namespace oneapi::dal::pca::test


@@ -16,23 +16,24 @@ R.E. Carhart, D.H. Smith, R. Venkataraghavan;
 Definition and Applications" JCICS 25, 64-73 (1985).

 """
-from rdkit.DataStructs import IntSparseIntVect
-from rdkit import Chem
+from rdkit import DataStructs
 from rdkit.Chem import rdMolDescriptors
 from rdkit.Chem.AtomPairs import Utils
-from rdkit import DataStructs

-from rdkit.Chem.rdMolDescriptors import GetAtomPairFingerprint,GetHashedAtomPairFingerprint
-GetAtomPairFingerprintAsIntVect=rdMolDescriptors.GetAtomPairFingerprint
+GetAtomPairFingerprint = rdMolDescriptors.GetAtomPairFingerprint
+GetAtomPairFingerprintAsIntVect = rdMolDescriptors.GetAtomPairFingerprint
+GetHashedAtomPairFingerprint = rdMolDescriptors.GetHashedAtomPairFingerprint
+
+numPathBits = rdMolDescriptors.AtomPairsParameters.numPathBits
+_maxPathLen = (1 << numPathBits) - 1
+numFpBits = numPathBits + 2 * rdMolDescriptors.AtomPairsParameters.codeSize
+fpLen = 1 << numFpBits

-numPathBits=rdMolDescriptors.AtomPairsParameters.numPathBits
-_maxPathLen=(1<<numPathBits)-1
-numFpBits=numPathBits+2*rdMolDescriptors.AtomPairsParameters.codeSize
-fpLen=1<<numFpBits

-def pyScorePair(at1,at2,dist,atomCodes=None):
+def pyScorePair(at1, at2, dist, atomCodes=None):
   """ Returns a score for an individual atom pair.

+  >>> from rdkit import Chem
   >>> m = Chem.MolFromSmiles('CCCCC')
   >>> c1 = Utils.GetAtomCode(m.GetAtomWithIdx(0))
   >>> c2 = Utils.GetAtomCode(m.GetAtomWithIdx(1))

# $Id$
#
#  Copyright (C) 2004-2007 Greg Landrum and Rational Discovery LLC
#
#   @@ All Rights Reserved @@
#  This file is part of the RDKit.
#  The contents are covered by the terms of the BSD license
#  which is included in the file license.txt, found at the root
#  of the RDKit source tree.
#
""" Contains an implementation of Atom-pair fingerprints, as
described in:

R.E. Carhart, D.H. Smith, R. Venkataraghavan;
"Atom Pairs as Molecular Features in Structure-Activity Studies:
Definition and Applications" JCICS 25, 64-73 (1985).

"""
from rdkit.DataStructs import IntSparseIntVect
from rdkit import Chem
from rdkit.Chem import rdMolDescriptors
from rdkit.Chem.AtomPairs import Utils
from rdkit import DataStructs

from rdkit.Chem.rdMolDescriptors import GetAtomPairFingerprint,GetHashedAtomPairFingerprint
GetAtomPairFingerprintAsIntVect=rdMolDescriptors.GetAtomPairFingerprint

numPathBits=rdMolDescriptors.AtomPairsParameters.numPathBits
_maxPathLen=(1<<numPathBits)-1
numFpBits=numPathBits+2*rdMolDescriptors.AtomPairsParameters.codeSize
fpLen=1<<numFpBits

def pyScorePair(at1,at2,dist,atomCodes=None):
  """ Returns a score for an individual atom pair.

  >>> m = Chem.MolFromSmiles('CCCCC')
  >>> c1 = Utils.GetAtomCode(m.GetAtomWithIdx(0))
  >>> c2 = Utils.GetAtomCode(m.GetAtomWithIdx(1))
  >>> c3 = Utils.GetAtomCode(m.GetAtomWithIdx(2))
  >>> t = 1 | min(c1,c2)<<numPathBits | max(c1,c2)<<(rdMolDescriptors.AtomPairsParameters.codeSize+numPathBits)
  >>> pyScorePair(m.GetAtomWithIdx(0),m.GetAtomWithIdx(1),1)==t
  1
  >>> pyScorePair(m.GetAtomWithIdx(1),m.GetAtomWithIdx(0),1)==t
  1
  >>> t = 2 | min(c1,c3)<<numPathBits | max(c1,c3)<<(rdMolDescriptors.AtomPairsParameters.codeSize+numPathBits)
  >>> pyScorePair(m.GetAtomWithIdx(0),m.GetAtomWithIdx(2),2)==t
  1
  >>> pyScorePair(m.GetAtomWithIdx(0),m.GetAtomWithIdx(2),2,
  ...  atomCodes=(Utils.GetAtomCode(m.GetAtomWithIdx(0)),Utils.GetAtomCode(m.GetAtomWithIdx(2))))==t
  1

  """
  if not atomCodes:
    code1 = Utils.GetAtomCode(at1)
    code2 = Utils.GetAtomCode(at2)
  else:
    code1,code2=atomCodes
  accum = int(dist) % _maxPathLen
  accum |= min(code1,code2) << numPathBits
  accum |= max(code1,code2) << (rdMolDescriptors.AtomPairsParameters.codeSize+numPathBits)
  return accum

def ExplainPairScore(score):
  """
  >>> m = Chem.MolFromSmiles('C=CC')
  >>> score = pyScorePair(m.GetAtomWithIdx(0),m.GetAtomWithIdx(1),1)
  >>> ExplainPairScore(score)
  (('C', 1, 1), 1, ('C', 2, 1))
  >>> score = pyScorePair(m.GetAtomWithIdx(0),m.GetAtomWithIdx(2),2)
  >>> ExplainPairScore(score)
  (('C', 1, 0), 2, ('C', 1, 1))
  >>> score = pyScorePair(m.GetAtomWithIdx(1),m.GetAtomWithIdx(2),1)
  >>> ExplainPairScore(score)
  (('C', 1, 0), 1, ('C', 2, 1))
  >>> score = pyScorePair(m.GetAtomWithIdx(2),m.GetAtomWithIdx(1),1)
  >>> ExplainPairScore(score)
  (('C', 1, 0), 1, ('C', 2, 1))

  """
  codeMask = (1<<rdMolDescriptors.AtomPairsParameters.codeSize)-1
  pathMask = (1<<numPathBits)-1
  dist = score&pathMask

  score = score>>numPathBits
  code1 = score&codeMask
  score = score>>rdMolDescriptors.AtomPairsParameters.codeSize
  code2 = score&codeMask

  res = Utils.ExplainAtomCode(code1),dist,Utils.ExplainAtomCode(code2)
  return res

def GetAtomPairFingerprintAsBitVect(mol):
  """ Returns the Atom-pair fingerprint for a molecule as
  a SparseBitVect. Note that this doesn't match the standard
  definition of atom pairs, which uses counts of the
  pairs, not just their presence.

  **Arguments**:

    - mol: a molecule

  **Returns**: a SparseBitVect

  >>> m = Chem.MolFromSmiles('CCC')
  >>> v = [ pyScorePair(m.GetAtomWithIdx(0),m.GetAtomWithIdx(1),1),
  ...       pyScorePair(m.GetAtomWithIdx(0),m.GetAtomWithIdx(2),2),
  ...     ]
  >>> v.sort()
  >>> fp = GetAtomPairFingerprintAsBitVect(m)
  >>> list(fp.GetOnBits())==v
  True

  """
  res = DataStructs.SparseBitVect(fpLen)
  fp = rdMolDescriptors.GetAtomPairFingerprint(mol)
  for val in fp.GetNonzeroElements().keys():
    res.SetBit(val)
  return res

#------------------------------------
#
#  doctest boilerplate
#
def _test():
  import doctest,sys
  return doctest.testmod(sys.modules["__main__"])

if __name__ == '__main__':
  import sys
  failed,tried = _test()
  sys.exit(failed)

Though I have no particular objection to this change, I wonder why you made it. Is the `from x import y` pattern considered bad now?


@@ -75,3 +75,15 @@ const Outfit* Outfits::getOutfitByLookType(PlayerSex_t sex, uint16_t lookType) c
 	}
 	return nullptr;
 }
+
+const Outfit* Outfits::getOutfitByLookType(uint16_t lookType) const
+{
+	for (uint8_t sex = 0; sex <= 1; sex++) {
+		for (const Outfit& outfit : outfits[sex]) {
+			if (outfit.lookType == lookType) {
+				return &outfit;
+			}
+		}
+	}
+	return nullptr;
+}

/**
 * The Forgotten Server - a free and open-source MMORPG server emulator
 * Copyright (C) 2019  Mark Samman <mark.samman@gmail.com>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, write to the Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */

#include "otpch.h"

#include "outfit.h"

#include "pugicast.h"
#include "tools.h"

bool Outfits::loadFromXml()
{
	pugi::xml_document doc;
	pugi::xml_parse_result result = doc.load_file("data/XML/outfits.xml");
	if (!result) {
		printXMLError("Error - Outfits::loadFromXml", "data/XML/outfits.xml", result);
		return false;
	}

	for (auto outfitNode : doc.child("outfits").children()) {
		pugi::xml_attribute attr;
		if ((attr = outfitNode.attribute("enabled")) && !attr.as_bool()) {
			continue;
		}

		if (!(attr = outfitNode.attribute("type"))) {
			std::cout << "[Warning - Outfits::loadFromXml] Missing outfit type." << std::endl;
			continue;
		}

		uint16_t type = pugi::cast<uint16_t>(attr.value());
		if (type > PLAYERSEX_LAST) {
			std::cout << "[Warning - Outfits::loadFromXml] Invalid outfit type " << type << "." << std::endl;
			continue;
		}

		pugi::xml_attribute lookTypeAttribute = outfitNode.attribute("looktype");
		if (!lookTypeAttribute) {
			std::cout << "[Warning - Outfits::loadFromXml] Missing looktype on outfit." << std::endl;
			continue;
		}

		outfits[type].emplace_back(
			outfitNode.attribute("name").as_string(),
			pugi::cast<uint16_t>(lookTypeAttribute.value()),
			outfitNode.attribute("premium").as_bool(),
			outfitNode.attribute("unlocked").as_bool(true)
		);
	}
	return true;
}

const Outfit* Outfits::getOutfitByLookType(PlayerSex_t sex, uint16_t lookType) const
{
	for (const Outfit& outfit : outfits[sex]) {
		if (outfit.lookType == lookType) {
			return &outfit;
		}
	}
	return nullptr;
}

There are enums for genders + `PLAYERSEX_LAST`.