test: multiple subscribe with multiple messages

--- test/CoreApi/PubSubApiTest.cs
+++ test/CoreApi/PubSubApiTest.cs
@@ -121,6 +121,36 @@
             }
         }

+        [TestMethod]
+        public async Task Multiple_Subscribe_Mutiple_Messages()
+        {
+            messageCount = 0;
+            var messages = "hello world this is pubsub".Split();
+            var ipfs = TestFixture.Ipfs;
+            var topic = "net-ipfs-api-test-" + Guid.NewGuid().ToString();
+            var cs = new CancellationTokenSource();
+            Action<PublishedMessage> processMessage = (msg) =>
+            {
+                Interlocked.Increment(ref messageCount);
+            };
+            try
+            {
+                await ipfs.PubSub.Subscribe(topic, processMessage, cs.Token);
+                await ipfs.PubSub.Subscribe(topic, processMessage, cs.Token);
+                foreach (var msg in messages)
+                {
+                    await ipfs.PubSub.Publish(topic, msg);
+                }
+
+                await Task.Delay(1000);
+                Assert.AreEqual(messages.Length * 2, messageCount);
+            }
+            finally
+            {
+                cs.Cancel();
+            }
+        }
+
         volatile int messageCount1 = 0;

         [TestMethod]


Fixed the UI label "And update estimate" to fit on one line

--- src/JiraSVN.Plugin/UI/IssuesList.Designer.cs
+++ src/JiraSVN.Plugin/UI/IssuesList.Designer.cs
@@ -104,11 +104,11 @@
             ((System.ComponentModel.ISupportInitialize)(possibleAssignmentsBindingSource)).BeginInit();
             ((System.ComponentModel.ISupportInitialize)(this._binding)).BeginInit();
             ((System.ComponentModel.ISupportInitialize)(actionsAvailableBindingSource)).BeginInit();
-            this._filterGroup.SuspendLayout();
-            this.tableLayoutPanel3.SuspendLayout();
             ((System.ComponentModel.ISupportInitialize)(filtersBindingSource)).BeginInit();
             ((System.ComponentModel.ISupportInitialize)(statusFilterBindingSource)).BeginInit();
             ((System.ComponentModel.ISupportInitialize)(assignmentFilterBindingSource)).BeginInit();
+            this._filterGroup.SuspendLayout();
+            this.tableLayoutPanel3.SuspendLayout();
             this._issuesGroup.SuspendLayout();
             this._contextMenu.SuspendLayout();
             this.statusGroup.SuspendLayout();
@@ -195,11 +195,100 @@
             label6.Anchor = System.Windows.Forms.AnchorStyles.Left;
             label6.AutoSize = true;
             label6.DataBindings.Add(new System.Windows.Forms.Binding("Enabled", this._binding, "AddWorklog", true, System.Windows.Forms.DataSourceUpdateMode.OnPropertyChanged));
-            label6.Location = new System.Drawing.Point(299, 7);
+            label6.Location = new System.Drawing.Point(294, 7);
             label6.Name = "label6";
             label6.Size = new System.Drawing.Size(106, 13);
             label6.TabIndex = 2;
             label6.Text = "and update estimate:";
+            //
+            // filtersBindingSource
+            //
+            filtersBindingSource.DataMember = "Filters";
+            filtersBindingSource.DataSource = this._binding;
+            //
+            // label2
+            //
+            label2.Anchor = System.Windows.Forms.AnchorStyles.Left;
+            label2.AutoSize = true;
+            label2.Location = new System.Drawing.Point(3, 7);
+            label2.Name = "label2";
+            label2.Size = new System.Drawing.Size(61, 13);
+            label2.TabIndex = 0;
+            label2.Text = "Apply Filter:";
+            //
+            // label3
+            //
+            label3.Anchor = System.Windows.Forms.AnchorStyles.Right;
+            label3.AutoSize = true;
+            label3.Location = new System.Drawing.Point(358, 34);
+            label3.Name = "label3";
+            label3.Size = new System.Drawing.Size(51, 13);
+            label3.TabIndex = 6;
+            label3.Text = "Contains:";
+            //
+            // statusFilterBindingSource
+            //
+            statusFilterBindingSource.DataMember = "StatusFilter";
+            statusFilterBindingSource.DataSource = this._binding;
+            //
+            // label1
+            //
+            label1.Anchor = System.Windows.Forms.AnchorStyles.Left;
+            label1.AutoSize = true;
+            label1.Location = new System.Drawing.Point(3, 34);
+            label1.Name = "label1";
+            label1.Size = new System.Drawing.Size(65, 13);
+            label1.TabIndex = 2;
+            label1.Text = "Assinged to:";
+            //
+            // label4
+            //
+            label4.Anchor = System.Windows.Forms.AnchorStyles.Right;
+            label4.AutoSize = true;
+            label4.Location = new System.Drawing.Point(201, 34);
+            label4.Name = "label4";
+            label4.Size = new System.Drawing.Size(40, 13);
+            label4.TabIndex = 4;
+            label4.Text = "Status:";
+            //
+            // assignmentFilterBindingSource
+            //
+            assignmentFilterBindingSource.DataMember = "AssignmentFilter";
+            assignmentFilterBindingSource.DataSource = this._binding;
+            //
+            // hdrId
+            //
+            hdrId.Text = "Id";
+            //
+            // hdrSummary
+            //
+            hdrSummary.Text = "Summary";
+            hdrSummary.Width = 400;
+            //
+            // hdrAssignedTo
+            //
+            hdrAssignedTo.Text = "Assigned To";
+            hdrAssignedTo.Width = 100;
+            //
+            // hdrReportedBy
+            //
+            hdrReportedBy.Text = "Reported By";
+            hdrReportedBy.Width = 100;
+            //
+            // hdrLastMod
+            //
+            hdrLastMod.Text = "Last Modified";
+            hdrLastMod.Width = 100;
+            //
+            // hdrCreated
+            //
+            hdrCreated.Text = "Created On";
+            hdrCreated.Width = 100;
+            //
+            // hdrStatus
+            //
+            hdrStatus.Text = "Status";
+            hdrStatus.Width = 100;
             //
             // _filterGroup
             //
@@ -255,11 +344,6 @@
             this._filters.Size = new System.Drawing.Size(548, 21);
             this._filters.TabIndex = 1;
             //
-            // filtersBindingSource
-            //
-            filtersBindingSource.DataMember = "Filters";
-            filtersBindingSource.DataSource = this._binding;
-            //
             // _search
             //
             this._search.DataBindings.Add(new System.Windows.Forms.Binding("Text", this._binding, "TextFilter", true, System.Windows.Forms.DataSourceUpdateMode.Never));
@@ -269,26 +353,6 @@
             this._search.Size = new System.Drawing.Size(212, 20);
             this._search.TabIndex = 7;
             this._search.TextChanged += new System.EventHandler(this._search_TextChanged);
-            //
-            // label2
-            //
-            label2.Anchor = System.Windows.Forms.AnchorStyles.Left;
-            label2.AutoSize = true;
-            label2.Location = new System.Drawing.Point(3, 7);
-            label2.Name = "label2";
-            label2.Size = new System.Drawing.Size(61, 13);
-            label2.TabIndex = 0;
-            label2.Text = "Apply Filter:";
-            //
-            // label3
-            //
-            label3.Anchor = System.Windows.Forms.AnchorStyles.Right;
-            label3.AutoSize = true;
-            label3.Location = new System.Drawing.Point(358, 34);
-            label3.Name = "label3";
-            label3.Size = new System.Drawing.Size(51, 13);
-            label3.TabIndex = 6;
-            label3.Text = "Contains:";
             //
             // _status
             //
@@ -303,31 +367,6 @@
             this._status.Size = new System.Drawing.Size(102, 21);
             this._status.TabIndex = 5;
             //
-            // statusFilterBindingSource
-            //
-            statusFilterBindingSource.DataMember = "StatusFilter";
-            statusFilterBindingSource.DataSource = this._binding;
-            //
-            // label1
-            //
-            label1.Anchor = System.Windows.Forms.AnchorStyles.Left;
-            label1.AutoSize = true;
-            label1.Location = new System.Drawing.Point(3, 34);
-            label1.Name = "label1";
-            label1.Size = new System.Drawing.Size(65, 13);
-            label1.TabIndex = 2;
-            label1.Text = "Assinged to:";
-            //
-            // label4
-            //
-            label4.Anchor = System.Windows.Forms.AnchorStyles.Right;
-            label4.AutoSize = true;
-            label4.Location = new System.Drawing.Point(201, 34);
-            label4.Name = "label4";
-            label4.Size = new System.Drawing.Size(40, 13);
-            label4.TabIndex = 4;
-            label4.Text = "Status:";
-            //
             // _assigned
             //
             this._assigned.DataBindings.Add(new System.Windows.Forms.Binding("IndexSelected", this._binding, "SelectedAssignmentFilter", true, System.Windows.Forms.DataSourceUpdateMode.OnPropertyChanged));
@@ -340,45 +379,6 @@
             this._assigned.Name = "_assigned";
             this._assigned.Size = new System.Drawing.Size(102, 21);
             this._assigned.TabIndex = 3;
-            //
-            // assignmentFilterBindingSource
-            //
-            assignmentFilterBindingSource.DataMember = "AssignmentFilter";
-            assignmentFilterBindingSource.DataSource = this._binding;
-            //
-            // hdrId
-            //
-            hdrId.Text = "Id";
-            //
-            // hdrSummary
-            //
-            hdrSummary.Text = "Summary";
-            hdrSummary.Width = 400;
-            //
-            // hdrAssignedTo
-            //
-            hdrAssignedTo.Text = "Assigned To";
-            hdrAssignedTo.Width = 100;
-            //
-            // hdrReportedBy
-            //
-            hdrReportedBy.Text = "Reported By";
-            hdrReportedBy.Width = 100;
-            //
-            // hdrLastMod
-            //
-            hdrLastMod.Text = "Last Modified";
-            hdrLastMod.Width = 100;
-            //
-            // hdrCreated
-            //
-            hdrCreated.Text = "Created On";
-            hdrCreated.Width = 100;
-            //
-            // hdrStatus
-            //
-            hdrStatus.Text = "Status";
-            hdrStatus.Width = 100;
             //
             // _issuesGroup
             //
@@ -466,7 +466,7 @@
             this.tableLayoutPanel2.ColumnCount = 4;
             this.tableLayoutPanel2.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 76F));
             this.tableLayoutPanel2.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 50.15783F));
-            this.tableLayoutPanel2.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 114F));
+            this.tableLayoutPanel2.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 124F));
             this.tableLayoutPanel2.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 49.84217F));
             this.tableLayoutPanel2.Controls.Add(this._doTakeAction, 0, 0);
             this.tableLayoutPanel2.Controls.Add(this._assignTo, 3, 0);
@@ -502,9 +502,9 @@
             this._assignTo.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
             this._assignTo.FormattingEnabled = true;
             this._assignTo.IndexSelected = -1;
-            this._assignTo.Location = new System.Drawing.Point(413, 3);
+            this._assignTo.Location = new System.Drawing.Point(418, 3);
             this._assignTo.Name = "_assignTo";
-            this._assignTo.Size = new System.Drawing.Size(214, 21);
+            this._assignTo.Size = new System.Drawing.Size(209, 21);
             this._assignTo.TabIndex = 9;
             //
             // _takeAction
@@ -518,7 +518,7 @@
             this._takeAction.IndexSelected = -1;
             this._takeAction.Location = new System.Drawing.Point(79, 3);
             this._takeAction.Name = "_takeAction";
-            this._takeAction.Size = new System.Drawing.Size(214, 21);
+            this._takeAction.Size = new System.Drawing.Size(209, 21);
             this._takeAction.TabIndex = 7;
             //
             // _doAssignTo
@@ -527,9 +527,9 @@
             this._doAssignTo.DataBindings.Add(new System.Windows.Forms.Binding("Checked", this._binding, "AssignTo", true, System.Windows.Forms.DataSourceUpdateMode.OnPropertyChanged));
             this._doAssignTo.DataBindings.Add(new System.Windows.Forms.Binding("Enabled", this._binding, "PerformAction", true));
             this._doAssignTo.Dock = System.Windows.Forms.DockStyle.Fill;
-            this._doAssignTo.Location = new System.Drawing.Point(299, 3);
+            this._doAssignTo.Location = new System.Drawing.Point(294, 3);
             this._doAssignTo.Name = "_doAssignTo";
-            this._doAssignTo.Size = new System.Drawing.Size(108, 21);
+            this._doAssignTo.Size = new System.Drawing.Size(118, 21);
             this._doAssignTo.TabIndex = 8;
             this._doAssignTo.Text = "and assign to:";
             this._doAssignTo.UseVisualStyleBackColor = true;
@@ -580,9 +580,9 @@
             this._worklogAction.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
             this._worklogAction.FormattingEnabled = true;
             this._worklogAction.IndexSelected = -1;
-            this._worklogAction.Location = new System.Drawing.Point(413, 3);
+            this._worklogAction.Location = new System.Drawing.Point(418, 3);
             this._worklogAction.Name = "_worklogAction";
-            this._worklogAction.Size = new System.Drawing.Size(129, 21);
+            this._worklogAction.Size = new System.Drawing.Size(126, 21);
             this._worklogAction.TabIndex = 3;
             //
             // remainingEstimateBindingSource
@@ -597,7 +597,7 @@
             this._worklog.Dock = System.Windows.Forms.DockStyle.Fill;
             this._worklog.Location = new System.Drawing.Point(79, 3);
             this._worklog.Name = "_worklog";
-            this._worklog.Size = new System.Drawing.Size(214, 20);
+            this._worklog.Size = new System.Drawing.Size(209, 20);
             this._worklog.TabIndex = 1;
             //
             // textBox1
@@ -605,9 +605,9 @@
             this.textBox1.DataBindings.Add(new System.Windows.Forms.Binding("Text", this._binding, "NewTimeEstimate", true));
             this.textBox1.DataBindings.Add(new System.Windows.Forms.Binding("Enabled", this._binding, "CanSpecifyNewEstimate", true));
             this.textBox1.Dock = System.Windows.Forms.DockStyle.Fill;
-            this.textBox1.Location = new System.Drawing.Point(548, 3);
+            this.textBox1.Location = new System.Drawing.Point(550, 3);
             this.textBox1.Name = "textBox1";
-            this.textBox1.Size = new System.Drawing.Size(79, 20);
+            this.textBox1.Size = new System.Drawing.Size(77, 20);
             this.textBox1.TabIndex = 4;
             //
             // _worklogGroup
@@ -630,7 +630,7 @@
             this.tableLayoutPanel1.ColumnCount = 5;
             this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 76F));
             this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 50F));
-            this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 114F));
+            this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 124F));
             this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 30.85586F));
             this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 19.14414F));
             this.tableLayoutPanel1.Controls.Add(this.textBox1, 4, 0);
@@ -695,13 +695,13 @@
             ((System.ComponentModel.ISupportInitialize)(possibleAssignmentsBindingSource)).EndInit();
             ((System.ComponentModel.ISupportInitialize)(this._binding)).EndInit();
             ((System.ComponentModel.ISupportInitialize)(actionsAvailableBindingSource)).EndInit();
+            ((System.ComponentModel.ISupportInitialize)(filtersBindingSource)).EndInit();
+            ((System.ComponentModel.ISupportInitialize)(statusFilterBindingSource)).EndInit();
+            ((System.ComponentModel.ISupportInitialize)(assignmentFilterBindingSource)).EndInit();
             this._filterGroup.ResumeLayout(false);
             this._filterGroup.PerformLayout();
             this.tableLayoutPanel3.ResumeLayout(false);
             this.tableLayoutPanel3.PerformLayout();
-            ((System.ComponentModel.ISupportInitialize)(filtersBindingSource)).EndInit();
-            ((System.ComponentModel.ISupportInitialize)(statusFilterBindingSource)).EndInit();
-            ((System.ComponentModel.ISupportInitialize)(assignmentFilterBindingSource)).EndInit();
             this._issuesGroup.ResumeLayout(false);
             this._contextMenu.ResumeLayout(false);
             this.statusGroup.ResumeLayout(false);


Add master notification for payments (#1956)

* Do not set flags for not implemented yet features

* Add notification for online payment

* fix review comments

--- src/JoinRpg.Services.Impl/PaymentsService.cs
+++ src/JoinRpg.Services.Impl/PaymentsService.cs
@@ -4,6 +4,8 @@
 using JoinRpg.Domain;
 using JoinRpg.Interfaces;
 using JoinRpg.Services.Interfaces;
+using JoinRpg.Services.Interfaces.Notification;
+using Microsoft.Extensions.Logging;
 using PscbApi;
 using PscbApi.Models;

@@ -14,6 +16,8 @@
 {

     private readonly IBankSecretsProvider _bankSecrets;
+    private readonly ILogger<PaymentsService> logger;
+    private readonly Lazy<IEmailService> emailService;
     private readonly IUriService _uriService;

     /// <inheritdoc />
@@ -21,10 +25,14 @@
         IUnitOfWork unitOfWork,
         IUriService uriService,
         IBankSecretsProvider bankSecrets,
-        ICurrentUserAccessor currentUserAccessor)
+        ICurrentUserAccessor currentUserAccessor,
+        Lazy<IEmailService> emailService,
+        ILogger<PaymentsService> logger)
         : base(unitOfWork, currentUserAccessor)
     {
         _bankSecrets = bankSecrets;
+        this.logger = logger;
+        this.emailService = emailService;
         _uriService = uriService;
     }

@@ -262,6 +270,8 @@
             return;
         }

+        logger.LogInformation("Updating online payment for ClaimId: {claimId}, ProjectId: {projectId}", fo.ClaimId, fo.ProjectId);
+
         var api = GetApi(fo.ProjectId, fo.ClaimId);
         string orderIdStr = fo.CommentId.ToString().PadLeft(10, '0');

@@ -283,6 +293,7 @@
         {
             if (paymentInfo.ErrorCode == ApiErrorCode.UnknownPayment)
             {
+                logger.LogInformation("Online payment for ClaimId: {claimId}, ProjectId: {projectId} is declined", fo.ClaimId, fo.ProjectId);
                 fo.State = FinanceOperationState.Declined;
                 fo.Changed = Now;
             }
@@ -291,8 +302,12 @@
                 UpdateFinanceOperationStatus(fo, paymentInfo.Payment);
                 if (fo.State == FinanceOperationState.Approved)
                 {
+                    logger.LogInformation("Online payment for ClaimId: {claimId}, ProjectId: {projectId} is accepted", fo.ClaimId, fo.ProjectId);
+
                     Claim claim = await GetClaimAsync(fo.ProjectId, fo.ClaimId);
                     claim.UpdateClaimFeeIfRequired(Now);
+
+                    await SendPaymentNotification(claim, fo.MoneyAmount);
                 }
             }
         }
@@ -317,6 +332,31 @@
         // TODO: Probably need to send some notifications?
     }

+    private async Task SendPaymentNotification(Claim claim, int sum)
+    {
+        try
+        {
+            var subscriptions = claim.GetSubscriptions(p => p.MoneyOperation, Enumerable.Empty<User>(), mastersOnly: true).ToList();
+            var email = new FinanceOperationEmail()
+            {
+                Claim = claim,
+                ProjectName = claim.Project.ProjectName,
+                Initiator = claim.Player,
+                InitiatorType = ParcipantType.Player,
+                Recipients = subscriptions,
+                //TODO[Localize]
+                Text = new MarkdownString(string.Format("Онлайн-оплата на сумму {0} подтверждена", sum)),
+                CommentExtraAction = null,
+            };
+
+            await emailService.Value.Email(email);
+        }
+        catch (Exception exc)
+        {
+            logger.LogError(exc, "Error during payment notification send");
+        }
+    }
+
     /// <inheritdoc />
     public async Task UpdateClaimPaymentAsync(int projectId, int claimId, int orderId)
         => await UpdateClaimPaymentAsync(await LoadFinanceOperationAsync(projectId, claimId, orderId));


looks like ms is the correct metric

looks like ms is the correct metric

--- src/Medidata.ZipkinTracer.Core/SpanTracer.cs
+++ src/Medidata.ZipkinTracer.Core/SpanTracer.cs
@@ -114,7 +114,7 @@
         private long GetTimeStamp()
         {
             var t = DateTime.UtcNow - new DateTime(1970, 1, 1);
-            return Convert.ToInt64(t.TotalMilliseconds * 1000);
+            return Convert.ToInt64(t.TotalMilliseconds);
         }
     }
 }


events are posted synchronously now

events are posted synchronously now

--- src/MessageBus/DSoft.Messaging/MessageBus.cs
+++ src/MessageBus/DSoft.Messaging/MessageBus.cs
@@ -166,11 +166,7 @@

 		private void Execute (Action<object,MessageBusEvent> Action, object Sender, MessageBusEvent Evnt)
 		{
-			Task.Factory.StartNew (() => {
-				Action (Sender, Evnt);
-			},
-				CancellationToken.None, TaskCreationOptions.LongRunning, TaskScheduler.Default);
-
+		    Action (Sender, Evnt);
 		}

 		/// <summary>


修复并发场景中有时无法正常获取到元数据的错误。 :construction:

修复并发场景中有时无法正常获取到元数据的错误。 :construction:

--- src/Metadata/Profiles/MetadataFileManager.cs
+++ src/Metadata/Profiles/MetadataFileManager.cs
@@ -40,11 +40,6 @@
 {
 	public class MetadataFileManager : IMetadataManager
 	{
-		#region 私有常量
-		private const int LOADED = 1;
-		private const int UNLOAD = 0;
-		#endregion
-
 		#region 成员字段
 		private readonly string _name;
 		private readonly object _syncRoot;
@@ -52,7 +47,7 @@
 		private readonly CommandCollection _commands;
 		private readonly EntityCollection _entities;

-		private int _loading;
+		private bool _isLoaded;
 		private IMetadataLoader _loader;
 		#endregion

@@ -64,6 +59,7 @@

 			_name = name.Trim();
 			_syncRoot = new object();
+			_isLoaded = false;
 			_loader = new MetadataFileLoader();
 			_metadatas = new MetadataCollection(this);
 			_commands = new CommandCollection(_metadatas);
@@ -102,9 +98,8 @@

 				_loader = value;

-				//如果当前元数据文件已经加载完成，则启动重新加载
-				if(_loading != UNLOAD)
-					this.Reload();
+				//将加载标记重置为未加载，以待后续重启加载
+				_isLoaded = false;
 			}
 		}

@@ -116,7 +111,7 @@
 			get
 			{
 				//如果未加载过元数据提供程序，则尝试加载它
-				if(_loading == UNLOAD)
+				if(!_isLoaded)
 					this.EnsureLoad();

 				return _metadatas;
@@ -131,7 +126,7 @@
 			get
 			{
 				//如果未加载过元数据提供程序，则尝试加载它
-				if(_loading == UNLOAD)
+				if(!_isLoaded)
 					this.EnsureLoad();

 				return _entities;
@@ -146,7 +141,7 @@
 			get
 			{
 				//如果未加载过元数据提供程序，则尝试加载它
-				if(_loading == UNLOAD)
+				if(!_isLoaded)
 					this.EnsureLoad();

 				return _commands;
@@ -169,6 +164,9 @@

 			_metadatas.Clear();
 			_metadatas.AddRange(items);
+
+			//设置加载标记为完成
+			_isLoaded = true;
 		}
 		#endregion

@@ -176,12 +174,13 @@
 		[System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
 		private void EnsureLoad()
 		{
-			if(_loading == UNLOAD)
-			{
-				var original = System.Threading.Interlocked.Exchange(ref _loading, LOADED);
-
-				if(original == UNLOAD)
-					this.Reload();
+			if(!_isLoaded)
+			{
+				lock(_syncRoot)
+				{
+					if(!_isLoaded)
+						this.Reload();
+				}
 			}
 		}
 		#endregion


Prevent multiple enumeration of headers

Prevent multiple enumeration of headers

--- src/ModernHttpClient.iOS/AFNetworkHandler.cs
+++ src/ModernHttpClient.iOS/AFNetworkHandler.cs
@@ -23,7 +23,7 @@

             if (request.Content != null) {
                 await request.Content.CopyToAsync(ms).ConfigureAwait(false);
-                headers = headers.Union(request.Content.Headers);
+                headers = headers.Union(request.Content.Headers).ToArray();
             }

             var rq = new NSMutableUrlRequest() {


ISessionImplementor - EOL normalization

ISessionImplementor - EOL normalization

--- src/NHibernate/Engine/ISessionImplementor.cs
+++ src/NHibernate/Engine/ISessionImplementor.cs
@@ -1,319 +1,319 @@
-using System;
-using System.Collections;
-using System.Collections.Generic;
-using System.Data;
-using NHibernate.AdoNet;
-using NHibernate.Cache;
-using NHibernate.Collection;
-using NHibernate.Engine.Query.Sql;
-using NHibernate.Event;
-using NHibernate.Hql;
-using NHibernate.Impl;
-using NHibernate.Loader.Custom;
-using NHibernate.Persister.Entity;
-using NHibernate.Transaction;
-using NHibernate.Type;
-
-namespace NHibernate.Engine
-{
-	///
-	/// Defines the internal contract between the <c>Session</c> and other parts of NHibernate
-	/// such as implementors of <c>Type</c> or <c>ClassPersister</c>
-	///
-	public interface ISessionImplementor
-	{
-		///
-		/// Initialize the session after its construction was complete
-		///
-		void Initialize();
-
-		///
-		/// Initialize the collection (if not already initialized)
-		///
-		/// <param name="collection"></param>
-		/// <param name="writing"></param>
-		void InitializeCollection(IPersistentCollection collection, bool writing);
-
-		// NH-268
-		///
-		/// Load an instance without checking if it was deleted. If it does not exist and isn't nullable, throw an exception.
-		/// This method may create a new proxy or return an existing proxy.
-		///
-		/// <param name="entityName">The entityName (or class full name) to load.</param>
-		/// <param name="id">The identifier of the object in the database.</param>
-		/// <param name="isNullable">Allow null instance</param>
-		/// <param name="eager">When enabled, the object is eagerly fetched.</param>
-		/// <returns>
-		/// A proxy of the object or an instance of the object if the <c>persistentClass</c> does not have a proxy.
-		/// </returns>
-		/// <exception cref="ObjectNotFoundException">No object could be found with that <c>id</c>.</exception>
-		object InternalLoad(string entityName, object id, bool eager, bool isNullable);
-
-		///
-		/// Load an instance immediately. Do not return a proxy.
-		///
-		/// <param name="entityName"></param>
-		/// <param name="id"></param>
-		/// <returns></returns>
-		object ImmediateLoad(string entityName, object id);
-
-		///
-		/// System time before the start of the transaction
-		///
-		/// <returns></returns>
-		long Timestamp { get; }
-
-		///
-		/// Get the creating SessionFactoryImplementor
-		///
-		/// <returns></returns>
-		ISessionFactoryImplementor Factory { get; }
-
-		///
-		/// Get the prepared statement <c>Batcher</c> for this session
-		///
-		IBatcher Batcher { get; }
-
-		///
-		/// Execute a <c>List()</c> query
-		///
-		/// <param name="query"></param>
-		/// <param name="parameters"></param>
-		/// <returns></returns>
-		IList List(string query, QueryParameters parameters);
-
-		///
-		/// Execute a <c>List()</c> expression query
-		///
-		/// <param name="queryExpression"></param>
-		/// <param name="parameters"></param>
-		/// <returns></returns>
-		IList List(IQueryExpression queryExpression, QueryParameters parameters);
-
-		///
-		/// Create a new instance of <c>Query</c> for the given query expression
-		/// <param name="queryExpression">A hibernate query expression</param>
-		/// <returns>The query</returns>
-		///
-		IQuery CreateQuery(IQueryExpression queryExpression);
-
-		void List(string query, QueryParameters parameters, IList results);
-
-		///
-		/// Strongly-typed version of <see cref="List(string,QueryParameters)" />
-		///
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Data;
+using NHibernate.AdoNet;
+using NHibernate.Cache;
+using NHibernate.Collection;
+using NHibernate.Engine.Query.Sql;
+using NHibernate.Event;
+using NHibernate.Hql;
+using NHibernate.Impl;
+using NHibernate.Loader.Custom;
+using NHibernate.Persister.Entity;
+using NHibernate.Transaction;
+using NHibernate.Type;
+
+namespace NHibernate.Engine
+{
+	///
+	/// Defines the internal contract between the <c>Session</c> and other parts of NHibernate
+	/// such as implementors of <c>Type</c> or <c>ClassPersister</c>
+	///
+	public interface ISessionImplementor
+	{
+		///
+		/// Initialize the session after its construction was complete
+		///
+		void Initialize();
+
+		///
+		/// Initialize the collection (if not already initialized)
+		///
+		/// <param name="collection"></param>
+		/// <param name="writing"></param>
+		void InitializeCollection(IPersistentCollection collection, bool writing);
+
+		// NH-268
+		///
+		/// Load an instance without checking if it was deleted. If it does not exist and isn't nullable, throw an exception.
+		/// This method may create a new proxy or return an existing proxy.
+		///
+		/// <param name="entityName">The entityName (or class full name) to load.</param>
+		/// <param name="id">The identifier of the object in the database.</param>
+		/// <param name="isNullable">Allow null instance</param>
+		/// <param name="eager">When enabled, the object is eagerly fetched.</param>
+		/// <returns>
+		/// A proxy of the object or an instance of the object if the <c>persistentClass</c> does not have a proxy.
+		/// </returns>
+		/// <exception cref="ObjectNotFoundException">No object could be found with that <c>id</c>.</exception>
+		object InternalLoad(string entityName, object id, bool eager, bool isNullable);
+
+		///
+		/// Load an instance immediately. Do not return a proxy.
+		///
+		/// <param name="entityName"></param>
+		/// <param name="id"></param>
+		/// <returns></returns>
+		object ImmediateLoad(string entityName, object id);
+
+		///
+		/// System time before the start of the transaction
+		///
+		/// <returns></returns>
+		long Timestamp { get; }
+
+		///
+		/// Get the creating SessionFactoryImplementor
+		///
+		/// <returns></returns>
+		ISessionFactoryImplementor Factory { get; }
+
+		///
+		/// Get the prepared statement <c>Batcher</c> for this session
+		///
+		IBatcher Batcher { get; }
+
+		///
+		/// Execute a <c>List()</c> query
+		///
+		/// <param name="query"></param>
+		/// <param name="parameters"></param>
+		/// <returns></returns>
+		IList List(string query, QueryParameters parameters);
+
+		///
+		/// Execute a <c>List()</c> expression query
+		///
+		/// <param name="queryExpression"></param>
+		/// <param name="parameters"></param>
+		/// <returns></returns>
+		IList List(IQueryExpression queryExpression, QueryParameters parameters);
+
+		///
+		/// Create a new instance of <c>Query</c> for the given query expression
+		/// <param name="queryExpression">A hibernate query expression</param>
+		/// <returns>The query</returns>
+		///
+		IQuery CreateQuery(IQueryExpression queryExpression);
+
+		void List(string query, QueryParameters parameters, IList results);
+
+		///
+		/// Strongly-typed version of <see cref="List(string,QueryParameters)" />
+		///
 		IList<T> List<T>(string query, QueryParameters queryParameters);

 		///
 		/// Strongly-typed version of <see cref="List(IQueryExpression,QueryParameters)" />
-		///
-		IList<T> List<T>(IQueryExpression queryExpression, QueryParameters queryParameters);
-
-		///
-		/// Strongly-typed version of <see cref="List(CriteriaImpl)" />
-		///
-		IList<T> List<T>(CriteriaImpl criteria);
-
-		void List(CriteriaImpl criteria, IList results);
-
-		IList List(CriteriaImpl criteria);
-
-		///
-		/// Execute an <c>Iterate()</c> query
-		///
-		/// <param name="query"></param>
-		/// <param name="parameters"></param>
-		/// <returns></returns>
-		IEnumerable Enumerable(string query, QueryParameters parameters);
-
-		///
-		/// Strongly-typed version of <see cref="Enumerable(string, QueryParameters)" />
-		///
-		IEnumerable<T> Enumerable<T>(string query, QueryParameters queryParameters);
-
-		///
-		/// Execute a filter
-		///
-		IList ListFilter(object collection, string filter, QueryParameters parameters);
-
-		///
-		/// Execute a filter (strongly-typed version).
-		///
-		IList<T> ListFilter<T>(object collection, string filter, QueryParameters parameters);
-
-		///
-		/// Collection from a filter
-		///
-		IEnumerable EnumerableFilter(object collection, string filter, QueryParameters parameters);
-
-		///
-		/// Strongly-typed version of <see cref="EnumerableFilter(object, string, QueryParameters)" />
-		///
-		IEnumerable<T> EnumerableFilter<T>(object collection, string filter, QueryParameters parameters);
-
-		///  Get the <see cref="IEntityPersister"/> for any instance
-		/// <param name="entityName">optional entity name </param>
-		/// <param name="obj">the entity instance </param>
-		IEntityPersister GetEntityPersister(string entityName, object obj);
-
-		///
-		/// Notify the session that an NHibernate transaction has begun.
-		///
-		void AfterTransactionBegin(ITransaction tx);
-
-		///
-		/// Notify the session that the transaction is about to complete
-		///
-		void BeforeTransactionCompletion(ITransaction tx);
-
-		///
-		/// Notify the session that the transaction completed, so we no longer own the old locks.
-		/// (Also we should release cache softlocks). May be called multiple times during the transaction
-		/// completion process.
-		///
-		void AfterTransactionCompletion(bool successful, ITransaction tx);
-
-		///
-		/// Return the identifier of the persistent object, or null if transient
-		///
-		object GetContextEntityIdentifier(object obj);
-
-		///
-		/// Instantiate the entity class, initializing with the given identifier
-		///
-		object Instantiate(string entityName, object id);
-
-		///
-		/// Execute an SQL Query
-		///
-		IList List(NativeSQLQuerySpecification spec, QueryParameters queryParameters);
-
-		void List(NativeSQLQuerySpecification spec, QueryParameters queryParameters, IList results);
-
-		///
-		/// Strongly-typed version of <see cref="List(NativeSQLQuerySpecification, QueryParameters)" />
-		///
-		IList<T> List<T>(NativeSQLQuerySpecification spec, QueryParameters queryParameters);
-
-		///  Execute an SQL Query
-		void ListCustomQuery(ICustomQuery customQuery, QueryParameters queryParameters, IList results);
-
-		IList<T> ListCustomQuery<T>(ICustomQuery customQuery, QueryParameters queryParameters);
-
-		///
-		/// Retrieve the currently set value for a filter parameter.
-		///
-		/// <param name="filterParameterName">The filter parameter name in the format
-		/// {FILTER_NAME.PARAMETER_NAME}.</param>
-		/// <returns>The filter parameter value.</returns>
-		object GetFilterParameterValue(string filterParameterName);
-
-		///
-		/// Retrieve the type for a given filter parameter.
-		///
-		/// <param name="filterParameterName">The filter parameter name in the format
-		/// {FILTER_NAME.PARAMETER_NAME}.</param>
-		/// <returns>The filter parameter type.</returns>
-		IType GetFilterParameterType(string filterParameterName);
-
-		///
-		/// Return the currently enabled filters.  The filter map is keyed by filter
-		/// name, with values corresponding to the <see cref="FilterImpl"/>
-		/// instance.
-		///
-		/// <returns>The currently enabled filters.</returns>
-		IDictionary<string, IFilter> EnabledFilters { get; }
-
-		IQuery GetNamedSQLQuery(string name);
-
-		IQueryTranslator[] GetQueries(string query, bool scalar); // NH specific for MultiQuery
-
-		IQueryTranslator[] GetQueries(IQueryExpression query, bool scalar); // NH specific for MultiQuery
-
-		IInterceptor Interceptor { get; }
-
-		///  Retrieves the configured event listeners from this event source.
-		EventListeners Listeners { get; }
-
-		int DontFlushFromFind { get; }
-
-		ConnectionManager ConnectionManager { get; }
-
-		bool IsEventSource { get; }
-
-		///
-		/// Get the entity instance associated with the given <tt>Key</tt>,
-		/// calling the Interceptor if necessary
-		///
-		object GetEntityUsingInterceptor(EntityKey key);
-
-		///  Get the persistence context for this session
-		IPersistenceContext PersistenceContext { get; }
-
-		CacheMode CacheMode { get; set; }
-
-		///
-		/// Is the <c>ISession</c> still open?
-		///
-		bool IsOpen { get; }
-
-		///
-		/// Is the <c>ISession</c> currently connected?
-		///
-		bool IsConnected { get; }
-
-		FlushMode FlushMode { get; set; }
-
-		string FetchProfile { get; set; }
-
-		///  The best guess entity name for an entity not in an association
-		string BestGuessEntityName(object entity);
-
-		///  The guessed entity name for an entity not in an association
-		string GuessEntityName(object entity);
-
-		IDbConnection Connection { get; }
-
-		IQuery GetNamedQuery(string queryName);
-
-		///  Determine whether the session is closed.  Provided separately from
-		/// {@link #isOpen()} as this method does not attempt any JTA synch
-		/// registration, where as {@link #isOpen()} does; which makes this one
-		/// nicer to use for most internal purposes.
-		///
-		/// <returns> True if the session is closed; false otherwise.
-		/// </returns>
-		bool IsClosed { get; }
-
-		void Flush();
-
-		///
-		/// Does this <tt>Session</tt> have an active Hibernate transaction
-		/// or is there a JTA transaction in progress?
-		///
-		bool TransactionInProgress { get; }
-
-		///  Retrieve the entity mode in effect for this session.
-		EntityMode EntityMode { get; }
-
-		///  Execute a native SQL update or delete query
-		int ExecuteNativeUpdate(NativeSQLQuerySpecification specification, QueryParameters queryParameters);
-
-		///  Execute a HQL update or delete query
-		int ExecuteUpdate(string query, QueryParameters queryParameters);
-
-		FutureCriteriaBatch FutureCriteriaBatch { get; }
-
-		FutureQueryBatch FutureQueryBatch { get; }
-
-		Guid SessionId { get; }
-
-		ITransactionContext TransactionContext { get; set; }
-
-		void CloseSessionFromDistributedTransaction();
-
-		EntityKey GenerateEntityKey(object id, IEntityPersister persister);
-
-		CacheKey GenerateCacheKey(object id, IType type, string entityOrRoleName);
-	}
-}
+		///
+		IList<T> List<T>(IQueryExpression queryExpression, QueryParameters queryParameters);
+
+		///
+		/// Strongly-typed version of <see cref="List(CriteriaImpl)" />
+		///
+		IList<T> List<T>(CriteriaImpl criteria);
+
+		void List(CriteriaImpl criteria, IList results);
+
+		IList List(CriteriaImpl criteria);
+
+		///
+		/// Execute an <c>Iterate()</c> query
+		///
+		/// <param name="query"></param>
+		/// <param name="parameters"></param>
+		/// <returns></returns>
+		IEnumerable Enumerable(string query, QueryParameters parameters);
+
+		///
+		/// Strongly-typed version of <see cref="Enumerable(string, QueryParameters)" />
+		///
+		IEnumerable<T> Enumerable<T>(string query, QueryParameters queryParameters);
+
+		///
+		/// Execute a filter
+		///
+		IList ListFilter(object collection, string filter, QueryParameters parameters);
+
+		///
+		/// Execute a filter (strongly-typed version).
+		///
+		IList<T> ListFilter<T>(object collection, string filter, QueryParameters parameters);
+
+		///
+		/// Collection from a filter
+		///
+		IEnumerable EnumerableFilter(object collection, string filter, QueryParameters parameters);
+
+		///
+		/// Strongly-typed version of <see cref="EnumerableFilter(object, string, QueryParameters)" />
+		///
+		IEnumerable<T> EnumerableFilter<T>(object collection, string filter, QueryParameters parameters);
+
+		///  Get the <see cref="IEntityPersister"/> for any instance
+		/// <param name="entityName">optional entity name </param>
+		/// <param name="obj">the entity instance </param>
+		IEntityPersister GetEntityPersister(string entityName, object obj);
+
+		///
+		/// Notify the session that an NHibernate transaction has begun.
+		///
+		void AfterTransactionBegin(ITransaction tx);
+
+		///
+		/// Notify the session that the transaction is about to complete
+		///
+		void BeforeTransactionCompletion(ITransaction tx);
+
+		///
+		/// Notify the session that the transaction completed, so we no longer own the old locks.
+		/// (Also we should release cache softlocks). May be called multiple times during the transaction
+		/// completion process.
+		///
+		void AfterTransactionCompletion(bool successful, ITransaction tx);
+
+		///
+		/// Return the identifier of the persistent object, or null if transient
+		///
+		object GetContextEntityIdentifier(object obj);
+
+		///
+		/// Instantiate the entity class, initializing with the given identifier
+		///
+		object Instantiate(string entityName, object id);
+
+		///
+		/// Execute an SQL Query
+		///
+		IList List(NativeSQLQuerySpecification spec, QueryParameters queryParameters);
+
+		void List(NativeSQLQuerySpecification spec, QueryParameters queryParameters, IList results);
+
+		///
+		/// Strongly-typed version of <see cref="List(NativeSQLQuerySpecification, QueryParameters)" />
+		///
+		IList<T> List<T>(NativeSQLQuerySpecification spec, QueryParameters queryParameters);
+
+		///  Execute an SQL Query
+		void ListCustomQuery(ICustomQuery customQuery, QueryParameters queryParameters, IList results);
+
+		IList<T> ListCustomQuery<T>(ICustomQuery customQuery, QueryParameters queryParameters);
+
+		///
+		/// Retrieve the currently set value for a filter parameter.
+		///
+		/// <param name="filterParameterName">The filter parameter name in the format
+		/// {FILTER_NAME.PARAMETER_NAME}.</param>
+		/// <returns>The filter parameter value.</returns>
+		object GetFilterParameterValue(string filterParameterName);
+
+		///
+		/// Retrieve the type for a given filter parameter.
+		///
+		/// <param name="filterParameterName">The filter parameter name in the format
+		/// {FILTER_NAME.PARAMETER_NAME}.</param>
+		/// <returns>The filter parameter type.</returns>
+		IType GetFilterParameterType(string filterParameterName);
+
+		///
+		/// Return the currently enabled filters.  The filter map is keyed by filter
+		/// name, with values corresponding to the <see cref="FilterImpl"/>
+		/// instance.
+		///
+		/// <returns>The currently enabled filters.</returns>
+		IDictionary<string, IFilter> EnabledFilters { get; }
+
+		IQuery GetNamedSQLQuery(string name);
+
+		IQueryTranslator[] GetQueries(string query, bool scalar); // NH specific for MultiQuery
+
+		IQueryTranslator[] GetQueries(IQueryExpression query, bool scalar); // NH specific for MultiQuery
+
+		IInterceptor Interceptor { get; }
+
+		///  Retrieves the configured event listeners from this event source.
+		EventListeners Listeners { get; }
+
+		int DontFlushFromFind { get; }
+
+		ConnectionManager ConnectionManager { get; }
+
+		bool IsEventSource { get; }
+
+		///
+		/// Get the entity instance associated with the given <tt>Key</tt>,
+		/// calling the Interceptor if necessary
+		///
+		object GetEntityUsingInterceptor(EntityKey key);
+
+		///  Get the persistence context for this session
+		IPersistenceContext PersistenceContext { get; }
+
+		CacheMode CacheMode { get; set; }
+
+		///
+		/// Is the <c>ISession</c> still open?
+		///
+		bool IsOpen { get; }
+
+		///
+		/// Is the <c>ISession</c> currently connected?
+		///
+		bool IsConnected { get; }
+
+		FlushMode FlushMode { get; set; }
+
+		string FetchProfile { get; set; }
+
+		///  The best guess entity name for an entity not in an association
+		string BestGuessEntityName(object entity);
+
+		///  The guessed entity name for an entity not in an association
+		string GuessEntityName(object entity);
+
+		IDbConnection Connection { get; }
+
+		IQuery GetNamedQuery(string queryName);
+
+		///  Determine whether the session is closed.  Provided separately from
+		/// {@link #isOpen()} as this method does not attempt any JTA synch
+		/// registration, where as {@link #isOpen()} does; which makes this one
+		/// nicer to use for most internal purposes.
+		///
+		/// <returns> True if the session is closed; false otherwise.
+		/// </returns>
+		bool IsClosed { get; }
+
+		void Flush();
+
+		///
+		/// Does this <tt>Session</tt> have an active Hibernate transaction
+		/// or is there a JTA transaction in progress?
+		///
+		bool TransactionInProgress { get; }
+
+		///  Retrieve the entity mode in effect for this session.
+		EntityMode EntityMode { get; }
+
+		///  Execute a native SQL update or delete query
+		int ExecuteNativeUpdate(NativeSQLQuerySpecification specification, QueryParameters queryParameters);
+
+		///  Execute a HQL update or delete query
+		int ExecuteUpdate(string query, QueryParameters queryParameters);
+
+		FutureCriteriaBatch FutureCriteriaBatch { get; }
+
+		FutureQueryBatch FutureQueryBatch { get; }
+
+		Guid SessionId { get; }
+
+		ITransactionContext TransactionContext { get; set; }
+
+		void CloseSessionFromDistributedTransaction();
+
+		EntityKey GenerateEntityKey(object id, IEntityPersister persister);
+
+		CacheKey GenerateCacheKey(object id, IType type, string entityOrRoleName);
+	}
+}


remove wrong documentation and introduce documentation

--- src/Okanshi.SplunkObserver/SplunkObserver.cs
+++ src/Okanshi.SplunkObserver/SplunkObserver.cs
@@ -44,9 +44,6 @@
             }
         }

-        /// <summary>
-        /// Override this in subclasses if you want to control how measurements are sent to Splunk
-        /// </summary>
         string ConvertMeasurementsToJson(IEnumerable<Metric> metrics)
         {
             var splunkEvents = metrics
@@ -58,9 +55,7 @@
             return events;
         }

-        /// <summary>
-        /// A general helper to turn a metric into a structure that become json
-        /// </summary>
+        /// <summary> A general helper to turn a metric into a structure that become json </summary>
         static Dictionary<string, object> MeasurementToDictionary(Metric metric)
         {
             var result = new Dictionary<string, object>
@@ -106,6 +101,7 @@
             return result;
         }

+        /// <summary>dispose </summary>
         public void Dispose()
         { }
     }


Allow registering a provider in DI (#2980)

If the user registered a concrete provider in the service collection for DI, then it will use the registration resolve it. Otherwise it falls back to activating a new instance as it was before (still using the container to fulfill dependencies).

--- src/Orleans/AssemblyLoader/AssemblyLoader.cs
+++ src/Orleans/AssemblyLoader/AssemblyLoader.cs
@@ -97,7 +97,7 @@
                     return null;
                 }

-                return (T)ActivatorUtilities.CreateInstance(serviceProvider, foundType);
+                return (T)ActivatorUtilities.GetServiceOrCreateInstance(serviceProvider, foundType);
             }
             catch (FileNotFoundException)
             {
@@ -118,7 +118,7 @@
                 var assembly = Assembly.Load(new AssemblyName(assemblyName));
                 var foundType = TypeUtils.GetTypes(assembly, type => typeof(T).IsAssignableFrom(type), logger).First();

-                return (T)ActivatorUtilities.CreateInstance(serviceProvider, foundType);
+                return (T)ActivatorUtilities.GetServiceOrCreateInstance(serviceProvider, foundType);
             }
             catch (Exception exc)
             {


adding method for shared parameter file validation

--- src/Parameters/Shared/SharedParameterFile.cs
+++ src/Parameters/Shared/SharedParameterFile.cs
@@ -261,6 +261,20 @@
             return $"*{sectionAsString}";
         }

+        /// <summary>
+        /// Returns true if shared parameter file is valid.
+        /// </summary>
+        /// <returns>
+        ///   <c>true</c> if this instance is valid; otherwise, <c>false</c>.
+        /// </returns>
+        public bool IsValid()
+        {
+            return Metadata.Version > 0 && Metadata.MinVersion > 0 &&
+                   Groups.Any() &&
+                   Parameters.Any();
+            }
+
+
         /// <inheritdoc />
         /// <summary>
         /// Clones this instance.


Add version to about dialog. (#11)

Add version to about dialog. (#11)

--- src/PaymentCalculator.Wpf/MainWindow.xaml.cs
+++ src/PaymentCalculator.Wpf/MainWindow.xaml.cs
@@ -1,6 +1,8 @@
 using PaymentCalculator.Model;
 using System.Collections.Generic;
+using System.Diagnostics;
 using System.Linq;
+using System.Reflection;
 using System.Windows;
 using VoidCore.Domain;
 using VoidCore.Domain.Events;
@@ -29,7 +31,8 @@

         private void About_MenuItem_Click(object sender, RoutedEventArgs e)
         {
-            MessageBox.Show("Author: Jeff Schreiner\nThis payment calculator is free to use and distribute.\nSee the source code at https://github.com/void-type");
+            var version = FileVersionInfo.GetVersionInfo(Assembly.GetExecutingAssembly().Location).ProductVersion;
+            MessageBox.Show($"Version: {version}\nAuthor: Jeff Schreiner\nThis payment calculator is free to use and distribute.\nSee the source code at https://github.com/void-type");
         }

         private void CalcButton_Click(object sender, RoutedEventArgs e)


draw nodes on top of edges

draw nodes on top of edges

--- src/Plainion.GraphViz/Visuals/GraphVisual.cs
+++ src/Plainion.GraphViz/Visuals/GraphVisual.cs
@@ -107,6 +107,22 @@

                 myDrawing = new DrawingVisual();

+                // first draw edges so that in case of overlap with nodes nodes are on top
+                foreach (var edge in transformationModule.Graph.Edges)
+                {
+                    var visual = new EdgeVisual(edge, Presentation);
+
+                    myDrawingElements.Add(edge.Id, visual);
+
+                    if (Presentation.Picking.Pick(edge))
+                    {
+                        var layoutState = layoutModule.GetLayout(edge);
+                        visual.Draw(layoutState);
+
+                        myDrawing.Children.Add(visual.Visual);
+                    }
+                }
+
                 foreach (var node in transformationModule.Graph.Nodes)
                 {
                     var visual = new NodeVisual(node, Presentation);
@@ -116,21 +132,6 @@
                     if (Presentation.Picking.Pick(node))
                     {
                         var layoutState = layoutModule.GetLayout(node);
-                        visual.Draw(layoutState);
-
-                        myDrawing.Children.Add(visual.Visual);
-                    }
-                }
-
-                foreach (var edge in transformationModule.Graph.Edges)
-                {
-                    var visual = new EdgeVisual(edge, Presentation);
-
-                    myDrawingElements.Add(edge.Id, visual);
-
-                    if (Presentation.Picking.Pick(edge))
-                    {
-                        var layoutState = layoutModule.GetLayout(edge);
                         visual.Draw(layoutState);

                         myDrawing.Children.Add(visual.Visual);
@@ -178,6 +179,19 @@
             }
             else
             {
+                // first draw edges so that in case of overlap with nodes nodes are on top
+                if (!myEdgeMaskJournal.IsEmpty)
+                {
+                    // EdgeMask module can only hide additional edges so no picking required here
+                    foreach (var edge in myEdgeMaskJournal.Entries)
+                    {
+                        SetVisibility((EdgeVisual)myDrawingElements[edge.Id], false, null);
+                    }
+
+                    myEdgeMaskJournal.Clear();
+                    InvalidateVisual();
+                }
+
                 if (!myNodeMaskJournal.IsEmpty)
                 {
                     foreach (var node in transformationModule.Graph.Nodes)
@@ -226,18 +240,6 @@
                     InvalidateVisual();
                 }

-                if (!myEdgeMaskJournal.IsEmpty)
-                {
-                    // EdgeMask module can only hide additional edges so no picking required here
-                    foreach (var edge in myEdgeMaskJournal.Entries)
-                    {
-                        SetVisibility((EdgeVisual)myDrawingElements[edge.Id], false, null);
-                    }
-
-                    myEdgeMaskJournal.Clear();
-                    InvalidateVisual();
-                }
-
                 if (!mySelectionJournal.IsEmpty)
                 {
                     foreach (var e in mySelectionJournal.Entries)


Formatting

Formatting

--- src/QuartzNET-DynamoDB/DynamoBootstrapper.cs
+++ src/QuartzNET-DynamoDB/DynamoBootstrapper.cs
@@ -17,30 +17,30 @@
                 CreateJobDetailTable(client);
             }

-			if (!TableExists(client, DynamoConfiguration.JobGroupTableName))
-			{
-				CreateJobGroupTable(client);
-			}
+            if (!TableExists(client, DynamoConfiguration.JobGroupTableName))
+            {
+                CreateJobGroupTable(client);
+            }

             if (!TableExists(client, DynamoConfiguration.TriggerTableName))
             {
                 CreateTriggerTable(client);
             }

-			if (!TableExists(client, DynamoConfiguration.TriggerGroupTableName))
+            if (!TableExists(client, DynamoConfiguration.TriggerGroupTableName))
             {
                 CreateTriggerGroupTable(client);
             }

-			if (!TableExists(client, DynamoConfiguration.SchedulerTableName))
-			{
-				CreateSchedulerTable(client);
-			}
-
-			if (!TableExists(client, DynamoConfiguration.CalendarTableName))
-			{
-				CreateCalendarTable(client);
-			}
+            if (!TableExists(client, DynamoConfiguration.SchedulerTableName))
+            {
+                CreateSchedulerTable(client);
+            }
+
+            if (!TableExists(client, DynamoConfiguration.CalendarTableName))
+            {
+                CreateCalendarTable(client);
+            }
         }

         private bool TableExists(IAmazonDynamoDB client, string tableName)
@@ -117,116 +117,116 @@
                 createResponse.TableDescription.TableStatus);
         }

-		private void CreateJobGroupTable(IAmazonDynamoDB client)
-		{
-			// Build a 'CreateTableRequest' for the new table
-			CreateTableRequest createRequest = new CreateTableRequest
-			{
-				TableName = DynamoConfiguration.JobGroupTableName,
-				AttributeDefinitions = new List<AttributeDefinition>()
-				{
-					new AttributeDefinition
-					{
-						AttributeName = "Name",
-						AttributeType = "S"
-					}
-				},
-				KeySchema = new List<KeySchemaElement>()
-				{
-					new KeySchemaElement
-					{
-						AttributeName = "Name",
-						KeyType = "HASH"
-					}
-				}
-			};
-
-			// Provisioned-throughput settings are required even though
-			// the local test version of DynamoDB ignores them
-			createRequest.ProvisionedThroughput = new ProvisionedThroughput(1, 1);
-
-			// Using the DynamoDB client, make a synchronous CreateTable request
-			CreateTableResponse createResponse;
-			createResponse = client.CreateTable(createRequest);
-
-			// Report the status of the new table...
-			Debug.WriteLine("\n\n Created the \"Job Group\" table successfully!\n    Status of the new table: '{0}'",
-				createResponse.TableDescription.TableStatus);
-		}
-
-		private void CreateCalendarTable(IAmazonDynamoDB client)
-		{
-			// Build a 'CreateTableRequest' for the new table
-			CreateTableRequest createRequest = new CreateTableRequest
-			{
-				TableName = DynamoConfiguration.CalendarTableName,
-				AttributeDefinitions = new List<AttributeDefinition>()
-				{
-					new AttributeDefinition
-					{
-						AttributeName = "Name",
-						AttributeType = "S"
-					}
-				},
-				KeySchema = new List<KeySchemaElement>()
-				{
-					new KeySchemaElement
-					{
-						AttributeName = "Name",
-						KeyType = "HASH"
-					}
-				}
-			};
-
-			// Provisioned-throughput settings are required even though
-			// the local test version of DynamoDB ignores them
-			createRequest.ProvisionedThroughput = new ProvisionedThroughput(1, 1);
-
-			// Using the DynamoDB client, make a synchronous CreateTable request
-			CreateTableResponse createResponse;
-			createResponse = client.CreateTable(createRequest);
-
-			// Report the status of the new table...
-			Debug.WriteLine("\n\n Created the \"Calendar\" table successfully!\n    Status of the new table: '{0}'",
-				createResponse.TableDescription.TableStatus);
-		}
-
-		private void CreateTriggerGroupTable(IAmazonDynamoDB client)
-		{
-			// Build a 'CreateTableRequest' for the new table
-			CreateTableRequest createRequest = new CreateTableRequest
-			{
-				TableName = DynamoConfiguration.TriggerGroupTableName,
-				AttributeDefinitions = new List<AttributeDefinition>()
-				{
-					new AttributeDefinition
-					{
-						AttributeName = "Name",
-						AttributeType = "S"
-					}
-				},
-				KeySchema = new List<KeySchemaElement>()
-				{
-					new KeySchemaElement
-					{
-						AttributeName = "Name",
-						KeyType = "HASH"
-					}
-				}
-			};
-
-			// Provisioned-throughput settings are required even though
-			// the local test version of DynamoDB ignores them
-			createRequest.ProvisionedThroughput = new ProvisionedThroughput(1, 1);
-
-			// Using the DynamoDB client, make a synchronous CreateTable request
-			CreateTableResponse createResponse;
-			createResponse = client.CreateTable(createRequest);
-
-			// Report the status of the new table...
-			Debug.WriteLine("\n\n Created the \"Trigger Group\" table successfully!\n    Status of the new table: '{0}'",
-				createResponse.TableDescription.TableStatus);
-		}
+        private void CreateJobGroupTable(IAmazonDynamoDB client)
+        {
+            // Build a 'CreateTableRequest' for the new table
+            CreateTableRequest createRequest = new CreateTableRequest
+            {
+                TableName = DynamoConfiguration.JobGroupTableName,
+                AttributeDefinitions = new List<AttributeDefinition>()
+                {
+                    new AttributeDefinition
+                    {
+                        AttributeName = "Name",
+                        AttributeType = "S"
+                    }
+                },
+                KeySchema = new List<KeySchemaElement>()
+                {
+                    new KeySchemaElement
+                    {
+                        AttributeName = "Name",
+                        KeyType = "HASH"
+                    }
+                }
+            };
+
+            // Provisioned-throughput settings are required even though
+            // the local test version of DynamoDB ignores them
+            createRequest.ProvisionedThroughput = new ProvisionedThroughput(1, 1);
+
+            // Using the DynamoDB client, make a synchronous CreateTable request
+            CreateTableResponse createResponse;
+            createResponse = client.CreateTable(createRequest);
+
+            // Report the status of the new table...
+            Debug.WriteLine("\n\n Created the \"Job Group\" table successfully!\n    Status of the new table: '{0}'",
+                createResponse.TableDescription.TableStatus);
+        }
+
+        private void CreateCalendarTable(IAmazonDynamoDB client)
+        {
+            // Build a 'CreateTableRequest' for the new table
+            CreateTableRequest createRequest = new CreateTableRequest
+            {
+                TableName = DynamoConfiguration.CalendarTableName,
+                AttributeDefinitions = new List<AttributeDefinition>()
+                {
+                    new AttributeDefinition
+                    {
+                        AttributeName = "Name",
+                        AttributeType = "S"
+                    }
+                },
+                KeySchema = new List<KeySchemaElement>()
+                {
+                    new KeySchemaElement
+                    {
+                        AttributeName = "Name",
+                        KeyType = "HASH"
+                    }
+                }
+            };
+
+            // Provisioned-throughput settings are required even though
+            // the local test version of DynamoDB ignores them
+            createRequest.ProvisionedThroughput = new ProvisionedThroughput(1, 1);
+
+            // Using the DynamoDB client, make a synchronous CreateTable request
+            CreateTableResponse createResponse;
+            createResponse = client.CreateTable(createRequest);
+
+            // Report the status of the new table...
+            Debug.WriteLine("\n\n Created the \"Calendar\" table successfully!\n    Status of the new table: '{0}'",
+                createResponse.TableDescription.TableStatus);
+        }
+
+        private void CreateTriggerGroupTable(IAmazonDynamoDB client)
+        {
+            // Build a 'CreateTableRequest' for the new table
+            CreateTableRequest createRequest = new CreateTableRequest
+            {
+                TableName = DynamoConfiguration.TriggerGroupTableName,
+                AttributeDefinitions = new List<AttributeDefinition>()
+                {
+                    new AttributeDefinition
+                    {
+                        AttributeName = "Name",
+                        AttributeType = "S"
+                    }
+                },
+                KeySchema = new List<KeySchemaElement>()
+                {
+                    new KeySchemaElement
+                    {
+                        AttributeName = "Name",
+                        KeyType = "HASH"
+                    }
+                }
+            };
+
+            // Provisioned-throughput settings are required even though
+            // the local test version of DynamoDB ignores them
+            createRequest.ProvisionedThroughput = new ProvisionedThroughput(1, 1);
+
+            // Using the DynamoDB client, make a synchronous CreateTable request
+            CreateTableResponse createResponse;
+            createResponse = client.CreateTable(createRequest);
+
+            // Report the status of the new table...
+            Debug.WriteLine("\n\n Created the \"Trigger Group\" table successfully!\n    Status of the new table: '{0}'",
+                createResponse.TableDescription.TableStatus);
+        }

         private void CreateTriggerTable(IAmazonDynamoDB client)
         {


Refactor: Some comments

Refactor: Some comments

--- src/ReniUI/Formatting/FormatterTokenGroup.cs
+++ src/ReniUI/Formatting/FormatterTokenGroup.cs
@@ -10,14 +10,17 @@
     {
         sealed class CacheContainer
         {
+            internal ISourcePartEdit[] Main;
             internal ISourcePartEdit[] Prefix;
-            internal ISourcePartEdit[] Main;
             internal ISourcePartEdit[] Suffix;
         }

         internal static FormatterTokenGroup Create(Syntax syntax)
             => new FormatterTokenGroup
-                (syntax.Token, syntax.RightNeighbor?.Token, syntax.RightSideSeparator() != SeparatorType.CloseSeparator);
+            (
+                syntax.Token,
+                syntax.RightNeighbor?.Token,
+                syntax.RightSideSeparator() != SeparatorType.CloseSeparator);

         static ISourcePartEdit[] CreateSourcePartEdits(IToken token, bool returnMain = true)
         {
@@ -27,8 +30,8 @@

         readonly CacheContainer Cache = new CacheContainer();
         readonly bool IsCloseSeparatorOnRightSide;
+        readonly IToken RightNeighbor;
         readonly IToken Token;
-        readonly IToken RightNeighbor;

         FormatterTokenGroup(IToken token, IToken rightNeighbor, bool isCloseSeparatorOnRightSide)
         {
@@ -37,6 +40,9 @@
             RightNeighbor = rightNeighbor;
         }

+        /// <summary>
+        /// Returns all edits, except the last. So it's all comments and whitespaces before the actual token
+        /// </summary>
         internal ISourcePartEdit[] Prefix
         {
             get
@@ -46,6 +52,9 @@
             }
         }

+        /// <summary>
+        /// Returns the last edits, except the last. So this is the actual token
+        /// </summary>
         internal ISourcePartEdit[] Main
         {
             get
@@ -55,6 +64,9 @@
             }
         }

+        /// <summary>
+        /// Returns the prefix edits of the right neighbor token
+        /// </summary>
         internal ISourcePartEdit[] Suffix
             => Cache.Suffix ?? (Cache.Suffix = CreateSourcePartEdits(RightNeighbor, returnMain: false));


Make CriHcaConstants public

Make CriHcaConstants public

--- src/VGAudio/Codecs/CriHca/CriHcaConstants.cs
+++ src/VGAudio/Codecs/CriHca/CriHcaConstants.cs
@@ -1,6 +1,6 @@
 namespace VGAudio.Codecs.CriHca
 {
-    internal static class CriHcaConstants
+    public static class CriHcaConstants
     {
         public const int SubframesPerFrame = 8;
         public const int SubFrameSamplesBits = 7;


Record parameters are documented by the constructor.

If we ever change the declaration section to the abbreviated syntax and drop the generated constructor, we can add the parameter documentation back here.

--- src/XmlDocMarkdown.Core/MarkdownGenerator.cs
+++ src/XmlDocMarkdown.Core/MarkdownGenerator.cs
@@ -387,6 +387,11 @@
 					{
 						var typeParameters = xmlDocMember.TypeParameters;
 						var parameters = xmlDocMember.Parameters;
+
+						// record parameters are documented by the constructor, so don't repeat them here
+						if (typeKind == TypeKind.Record)
+							parameters = new Collection<XmlDocParameter>();
+
 						if (typeParameters.Count + parameters.Count > 0)
 						{
 							writer.WriteLine();


Fixed .nolist

Fixed .nolist

--- orgASM/Assembler.cs
+++ orgASM/Assembler.cs
@@ -218,7 +218,8 @@
                             continue;

                         output.Add(new ListEntry(line, FileNames.Peek(), LineNumbers.Peek(), value, currentAddress, !noList));
-                        currentAddress += (ushort)value.Length;
+                        if (!noList)
+                            currentAddress += (ushort)value.Length;
                     }
                 }
             }


Fix screen offsetting not handling scaled game instances

By using `Content` instead, now the logic will get the X of the settings
overlay at the `Content` space, which can be scaled in the
`ScalingMode.Everything` mode.

And in the case of `ScalingMode.ExcludeOverlays`, a subcontainer
somewhere inside `Content` that's holding the screen stack would be scaled,
but `Content` won't be affected which is what we want in that case.

--- osu.Game/OsuGame.cs
+++ osu.Game/OsuGame.cs
@@ -1019,9 +1019,9 @@
             var horizontalOffset = 0f;

             if (Settings.IsLoaded && Settings.IsPresent)
-                horizontalOffset += ToLocalSpace(Settings.ScreenSpaceDrawQuad.TopRight).X * SIDE_OVERLAY_OFFSET_RATIO;
+                horizontalOffset += Content.ToLocalSpace(Settings.ScreenSpaceDrawQuad.TopRight).X * SIDE_OVERLAY_OFFSET_RATIO;
             if (Notifications.IsLoaded && Notifications.IsPresent)
-                horizontalOffset += (ToLocalSpace(Notifications.ScreenSpaceDrawQuad.TopLeft).X - DrawWidth) * SIDE_OVERLAY_OFFSET_RATIO;
+                horizontalOffset += (Content.ToLocalSpace(Notifications.ScreenSpaceDrawQuad.TopLeft).X - Content.DrawWidth) * SIDE_OVERLAY_OFFSET_RATIO;

             ScreenOffsetContainer.X = horizontalOffset;


Ensure all other dialogs and overlays are dismissed when the first run wizard is shown

--- osu.Game/OsuGame.cs
+++ osu.Game/OsuGame.cs
@@ -844,7 +844,7 @@
             Add(new MusicKeyBindingHandler());

             // side overlays which cancel each other.
-            var singleDisplaySideOverlays = new OverlayContainer[] { Settings, Notifications };
+            var singleDisplaySideOverlays = new OverlayContainer[] { Settings, Notifications, firstRunOverlay };

             foreach (var overlay in singleDisplaySideOverlays)
             {
@@ -869,7 +869,7 @@
             }

             // ensure only one of these overlays are open at once.
-            var singleDisplayOverlays = new OverlayContainer[] { chatOverlay, news, dashboard, beatmapListing, changelogOverlay, rankingsOverlay, wikiOverlay };
+            var singleDisplayOverlays = new OverlayContainer[] { firstRunOverlay, chatOverlay, news, dashboard, beatmapListing, changelogOverlay, rankingsOverlay, wikiOverlay };

             foreach (var overlay in singleDisplayOverlays)
             {


Changed comment on GetFrameworkConfigDefaults() to be more accurate

--- osu.Game/OsuGame.cs
+++ osu.Game/OsuGame.cs
@@ -1010,7 +1010,7 @@

         protected override IDictionary<FrameworkSetting, object> GetFrameworkConfigDefaults()
         {
-            // Overriding settings determined by Framework
+            // Overriding config defaults determined by Framework
             IDictionary<FrameworkSetting, object> defaultOverrides = new Dictionary<FrameworkSetting, object>();
             defaultOverrides.Add(FrameworkSetting.WindowMode, WindowMode.Fullscreen);
             return defaultOverrides;


SDA-2912 Split registry cleaning actions to elevated/non-elevated

--- installer/win/WixSharpInstaller/Symphony.cs
+++ installer/win/WixSharpInstaller/Symphony.cs
@@ -211,6 +211,14 @@
             // versions of SDA, so we clean up all known variations, and ignore any missing ones.
             new ElevatedManagedAction(CustomActions.CleanRegistry, Return.ignore, When.After, Step.RemoveFiles, Condition.BeingUninstalled ),

+
+            // CleanRegistryCurrentUser
+            //
+            // The registry keys stored under HKEY_CURRENT_USER can not be accessed through an ElevatedManagedAction, as
+            // elevated actions run as a different user (local system account rather than current user) so those keys
+            // are removed in this action.
+            new ManagedAction(CustomActions.CleanRegistryCurrentUser, Return.ignore, When.After, Step.RemoveFiles, Condition.BeingUninstalled ),
+
             // Start Symphony after installation is complete
             new InstalledFileAction(new Id("symphony_exe"), "", Return.asyncNoWait, When.After, Step.InstallFinalize, Condition.NOT_BeingRemoved)
         };
@@ -392,6 +400,48 @@
         {
             // Remove registry keys added for auto-launch

+            using( var key = Registry.Users.OpenSubKey(@"\.DEFAULT\Software\Microsoft\Windows\CurrentVersion\Run", true) )
+            {
+                if (key != null)
+                {
+                    key.DeleteValue("Symphony", false);
+                }
+            }
+
+
+            // Remove registry keys added by protocol handlers
+
+            using( var key = Registry.LocalMachine.OpenSubKey(@"Software\Classes", true) )
+            {
+                if (key != null)
+                {
+                    key.DeleteSubKeyTree("symphony", false);
+                }
+            }
+            using( var key = Registry.ClassesRoot.OpenSubKey(@"\", true) )
+            {
+                if (key != null)
+                {
+                    key.DeleteSubKeyTree("symphony", false);
+                }
+            }
+        }
+        catch (System.Exception e)
+        {
+            session.Log("Error executing CleanRegistry: " + e.ToString() );
+            return ActionResult.Success;
+        }
+        return ActionResult.Success;
+    }
+
+    // CleanRegistryCurrentUser custom action
+    [CustomAction]
+    public static ActionResult CleanRegistryCurrentUser(Session session)
+    {
+        try
+        {
+            // Remove registry keys added for auto-launch
+
             using( var key = Registry.CurrentUser.OpenSubKey(@"Software\Microsoft\Windows\CurrentVersion\Run", true) )
             {
                 if (key != null)
@@ -401,42 +451,20 @@
                     key.DeleteValue("electron.app.Symphony", false);
                 }
             }
-            using( var key = Registry.Users.OpenSubKey(@"\.DEFAULT\Software\Microsoft\Windows\CurrentVersion\Run", true) )
+
+            // Remove registry keys added by protocol handlers
+
+            using( var key = Registry.CurrentUser.OpenSubKey(@"Software\Classes", true) )
             {
                 if (key != null)
                 {
-                    key.DeleteValue("Symphony", false);
-                }
-            }
-
-
-            // Remove registry keys added by protocol handlers
-
-            using( var key = Registry.CurrentUser.OpenSubKey(@"Software\Classes", true) )
-            {
-                if (key != null)
-                {
                     key.DeleteSubKeyTree("symphony", false);
                 }
             }
-            using( var key = Registry.LocalMachine.OpenSubKey(@"Software\Classes", true) )
-            {
-                if (key != null)
-                {
-                    key.DeleteSubKeyTree("symphony", false);
-                }
-            }
-            using( var key = Registry.ClassesRoot.OpenSubKey(@"\", true) )
-            {
-                if (key != null)
-                {
-                    key.DeleteSubKeyTree("symphony", false);
-                }
-            }
         }
         catch (System.Exception e)
         {
-            session.Log("Error executing CleanRegistry: " + e.ToString() );
+            session.Log("Error executing CleanRegistryCurrentUser: " + e.ToString() );
             return ActionResult.Success;
         }
         return ActionResult.Success;


fix retrieval of ImageVersion environment variable (#2539)


Added hexists, zincr, zexists, zrange, zrrange

--- api/dotnet/Client.cs
+++ api/dotnet/Client.cs
@@ -1,4 +1,4 @@
-using System;
+using System;
 using System.Collections.Generic;
 using System.Linq;
 using System.Text;


Fix bootstrap CDN fallback test & link

Fix bootstrap CDN fallback test & link

--- src/live.asp.net/Views/Shared/_Layout.cshtml
+++ src/live.asp.net/Views/Shared/_Layout.cshtml
@@ -13,8 +13,10 @@
     </environment>
     <environment names="Staging,Production">
         <link rel="stylesheet" href="//ajax.aspnetcdn.com/ajax/bootstrap/3.3.5/css/bootstrap.min.css"
-              asp-fallback-href="~/lib/bootstrap/css/bootstrap.min.css"
-              asp-fallback-test-class="hidden" asp-fallback-test-property="visibility" asp-fallback-test-value="hidden" />
+              asp-fallback-href="~/lib/bootstrap/css/bootstrap.css"
+              asp-fallback-test-class="hidden"
+              asp-fallback-test-property="display"
+              asp-fallback-test-value="none!important" />
         <link rel="stylesheet" href="~/css/site.css" asp-file-version="true" />
     </environment>
 </head>


C# Service Client - IsMappedToException Bug Fix

--- csharp/service/Microsoft.Azure.Devices/HttpClientHelper.cs
+++ csharp/service/Microsoft.Azure.Devices/HttpClientHelper.cs
@@ -85,7 +85,7 @@
                    HttpMethod.Get,
                    new Uri(this.baseAddress, requestUri),
                    (requestMsg, token) => AddCustomHeaders(requestMsg, customHeaders),
-                   message => message.IsSuccessStatusCode || message.StatusCode == HttpStatusCode.NotFound,
+                   message => !(message.IsSuccessStatusCode || message.StatusCode == HttpStatusCode.NotFound),
                    async (message, token) => result = message.StatusCode == HttpStatusCode.NotFound ? (default(T)) : await ReadResponseMessageAsync<T>(message, token),
                    errorMappingOverrides,
                    cancellationToken);


* Better FileSharePointClient mock

* Better FileSharePointClient mock

--- dotnet/Util/SharePoint/trunk/src/I/FileSharePointClient.cs
+++ dotnet/Util/SharePoint/trunk/src/I/FileSharePointClient.cs
@@ -21,7 +21,12 @@
 using System.Configuration;
 using System.Diagnostics;
 using System.IO;
+using System.Linq;
 using System.Net;
+using System.Security.AccessControl;
+using System.Security.Principal;
+using System.Threading;
+using System.Xml.Serialization;

 using PPWCode.Util.SharePoint.I.Helpers;

@@ -36,9 +41,51 @@
     public class FileSharePointClient :
         ISharePointClient
     {
+        #region Helper classes
+
+        public class Document
+        {
+            public Document()
+            {
+            }
+
+            public Document(string relativeUrl, string fileName)
+            {
+                RelativeUrl = relativeUrl;
+                FileName = fileName;
+            }
+
+            [XmlAttribute(AttributeName = @"Url")]
+            public string RelativeUrl { get; set; }
+
+            [XmlAttribute(AttributeName = @"FileName")]
+            public string FileName { get; set; }
+        }
+
+        [XmlRoot(ElementName = @"Root")]
+        public class RootDocument
+        {
+            public RootDocument()
+            {
+            }
+
+            public RootDocument(IEnumerable<KeyValuePair<string, string>> documentMap)
+            {
+                Documents = documentMap
+                    .Select(kvp => new Document(kvp.Key, kvp.Value))
+                    .ToArray();
+            }
+
+            public Document[] Documents { get; set; }
+        }
+
+        #endregion
+
         #region Fields

         private static readonly string s_SharepointMock;
+        private static readonly Mutex s_Mutex = new Mutex(false, @"PPWCode.Util.SharePoint.I.FileSharePointClient");
+        private static readonly XmlSerializer s_Serializer = new XmlSerializer(typeof(RootDocument));

         #endregion

@@ -56,11 +103,83 @@

         #region Private Helpers

-        private static byte[] ReadFile(string filePath)
-        {
+        private static byte[] ReadFile(string fileName)
+        {
+            string filePath = Path.Combine(s_SharepointMock, fileName);
             using (FileStream fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read))
             {
                 return fileStream.ConvertToByteArray();
+            }
+        }
+
+        private static void WriteFile(string fileName, byte[] content)
+        {
+            string filePath = Path.Combine(s_SharepointMock, fileName);
+            using (BinaryWriter writer = new BinaryWriter(File.Open(filePath, FileMode.Create)))
+            {
+                writer.Write(content);
+            }
+        }
+
+        private static RootDocument GetRootDocument(string filePath)
+        {
+            s_Mutex.WaitOne();
+            try
+            {
+                using (FileStream stream = new FileStream(filePath, FileMode.Open))
+                {
+                    return (RootDocument)s_Serializer.Deserialize(stream);
+                }
+            }
+            finally
+            {
+                s_Mutex.ReleaseMutex();
+            }
+        }
+
+        private static IDictionary<string, string> GetDocumentMap()
+        {
+            RootDocument rootDocument = null;
+            string filePath = Path.Combine(s_SharepointMock, @"Documents.xml");
+            if (File.Exists(filePath))
+            {
+                rootDocument = GetRootDocument(filePath);
+            }
+
+            IDictionary<string, string> result;
+            if (rootDocument != null && rootDocument.Documents != null)
+            {
+                result = rootDocument
+                    .Documents
+                    .AsEnumerable()
+                    .ToDictionary(d => d.RelativeUrl, d => d.FileName);
+            }
+            else
+            {
+                result = new Dictionary<string, string>();
+            }
+
+            return result;
+        }
+
+        private static void SaveDocumentMap(IEnumerable<KeyValuePair<string, string>> documentMap)
+        {
+            if (documentMap != null)
+            {
+                string filePath = Path.Combine(s_SharepointMock, @"Documents.xml");
+                RootDocument rootDocument = new RootDocument(documentMap);
+                s_Mutex.WaitOne();
+                try
+                {
+                    using (StreamWriter writer = new StreamWriter(filePath))
+                    {
+                        s_Serializer.Serialize(writer, rootDocument);
+                    }
+                }
+                finally
+                {
+                    s_Mutex.ReleaseMutex();
+                }
             }
         }

@@ -77,24 +196,19 @@
         /// <inheritdoc cref="ISharePointClient.EnsureFolder" />
         public void EnsureFolder(string relativeUrl)
         {
-            if (string.IsNullOrEmpty(relativeUrl))
-            {
-                return;
-            }
-
-            string combinedPath = Path.Combine(s_SharepointMock, relativeUrl);
-            if (!Directory.Exists(combinedPath))
-            {
-                Directory.CreateDirectory(combinedPath);
-            }
         }

         /// <inheritdoc cref="ISharePointClient.DownloadDocument" />
         public SharePointDocument DownloadDocument(string relativeUrl)
         {
-            string filePath = Path.Combine(s_SharepointMock, relativeUrl);
-            byte[] buffer = ReadFile(filePath);
-            return new SharePointDocument(buffer);
+            string fileName;
+            IDictionary<string, string> documentMap = GetDocumentMap();
+            if (documentMap.TryGetValue(relativeUrl, out fileName))
+            {
+                byte[] buffer = ReadFile(fileName);
+                return new SharePointDocument(buffer);
+            }
+            return null;
         }

         /// <inheritdoc cref="ISharePointClient.UploadDocument" />
@@ -105,11 +219,22 @@
                 return;
             }

-            string filePath = Path.Combine(s_SharepointMock, relativeUrl);
-            using (BinaryWriter writer = new BinaryWriter(File.Open(filePath, FileMode.Create)))
-            {
-                writer.Write(doc.Content);
-            }
+            IDictionary<string, string> documentMap = GetDocumentMap();
+            string fileName;
+            if (documentMap.ContainsKey(relativeUrl))
+            {
+                fileName = documentMap[relativeUrl];
+            }
+            else
+            {
+                string tempFullFileName = Path
+                    .GetTempFileName()
+                    .Replace(".tmp", ".bin");
+                fileName = Path.GetFileName(tempFullFileName);
+                documentMap.Add(relativeUrl, fileName);
+                SaveDocumentMap(documentMap);
+            }
+            WriteFile(fileName, doc.Content);
         }

         /// <inheritdoc cref="ISharePointClient.ValidateUri" />
@@ -121,30 +246,41 @@
         /// <inheritdoc cref="ISharePointClient.OpenUri" />
         public void OpenUri(Uri uri)
         {
-            string url = uri.OriginalString;
-            if (!string.IsNullOrEmpty(url))
-            {
-                Process.Start(
-                    new ProcessStartInfo
-                    {
-                        UseShellExecute = true,
-                        FileName = url,
-                        Verb = "Open",
-                        LoadUserProfile = true
-                    });
-            }
+            Process.Start(new ProcessStartInfo
+            {
+                UseShellExecute = true,
+                FileName = s_SharepointMock,
+                Verb = "Open",
+                LoadUserProfile = true
+            });
         }

         /// <inheritdoc cref="ISharePointClient.SearchFiles" />
         public List<SharePointSearchResult> SearchFiles(string url)
         {
+            List<SharePointSearchResult> result = new List<SharePointSearchResult>();
+            IDictionary<string, string> documentMap = GetDocumentMap();
             Uri fileUri = new Uri(url);
-            string pathName = fileUri.GetComponents(UriComponents.Path, UriFormat.SafeUnescaped);
-            List<SharePointSearchResult> result = new List<SharePointSearchResult>();
-            foreach (string fileName in Directory.GetFiles(pathName))
+            string relativeUrl = @"/" + fileUri.GetComponents(UriComponents.Path, UriFormat.SafeUnescaped);
+            var pairs = documentMap
+                .Where(p => p.Key.StartsWith(relativeUrl));
+            foreach (var pair in pairs)
             {
                 SharePointSearchResult fileInformation = new SharePointSearchResult();
-                fileInformation.Properties.Add("FileName", fileName);
+                string physicalPathName = Path.Combine(s_SharepointMock, pair.Value);
+                FileSecurity fs = File.GetAccessControl(physicalPathName);
+                IdentityReference sid = fs.GetOwner(typeof(SecurityIdentifier));
+                IdentityReference ntAccount = sid.Translate(typeof(NTAccount));
+
+                fileInformation.Properties.Add("FileName", Path.GetFileName(pair.Key));
+                fileInformation.Properties.Add("ServerRelativeUrl", pair.Key);
+                fileInformation.Properties.Add("Description", string.Empty);
+                fileInformation.Properties.Add("MajorVersion", 1);
+                fileInformation.Properties.Add("MinorVersion", 1);
+                fileInformation.Properties.Add("ModifiedBy", ntAccount.Value);
+                fileInformation.Properties.Add("DateModified", File.GetLastWriteTime(physicalPathName));
+                fileInformation.Properties.Add("CreatedBy", ntAccount.Value);
+                fileInformation.Properties.Add("DateCreated", File.GetCreationTime(physicalPathName));
                 result.Add(fileInformation);
             }
             return result;


Send custom User-Agent header on sync request. Closes #47.

--- Assets/Scripts/System/GameSync.cs
+++ Assets/Scripts/System/GameSync.cs
@@ -76,7 +76,9 @@

     private void fetchPlaylistSubscriptions()
     {
-        WWW www = new WWW(library_url + "/api/v1/playlists/?api_key=" + api_key);
+        Dictionary<string, string> headers = new Dictionary<string, string>();
+        headers.Add("User-Agent", "Winnitron Launcher/2.0.0-rc2 (http://winnitron.com)");
+        WWW www = new WWW(library_url + "/api/v1/playlists/?api_key=" + api_key, null, headers);

         StartCoroutine(WaitForSubscriptionList(www));
     }
@@ -353,7 +355,6 @@
             installationMetadata.Add("executable", new JSONData(executable));
             installationMetadata.Add("image_url", new JSONData(imageURL));

-
             JSONClass keymap = new JSONClass();
             keymap.Add("template", new JSONData(keyTemplate));
             installationMetadata.Add("keys", keymap);


fix entity selection display bug when drawing changes

--- BCad/UI/View/RenderCanvas.xaml.cs
+++ BCad/UI/View/RenderCanvas.xaml.cs
@@ -64,6 +64,7 @@
             if (control != null)
             {
                 control.Redraw();
+                control.CheckAllSelection();
             }
         }


Closes #31.  KeggRestApi class now uses the WebClient.BaseAddress property to simplify URIs


solution of C Sharp

solution of C Sharp

--- leetcode/C_sharp/online_judge/leetcode/hard/Problem2402.cs
+++ leetcode/C_sharp/online_judge/leetcode/hard/Problem2402.cs
@@ -11,6 +11,10 @@
         public int MostBooked(int n, int[][] meetings)
         {
             int ret = 0;
+            int[] lastEndtimes = new int[n];
+            int[] bookedTimes = new int[n];
+
+

             return ret;
         }


Reacting to Logging changes

Reacting to Logging changes

--- test/Microsoft.AspNet.Mvc.FunctionalTests/TagHelperSampleTest.cs
+++ test/Microsoft.AspNet.Mvc.FunctionalTests/TagHelperSampleTest.cs
@@ -73,6 +73,10 @@
             {
                 return new TestLogger();
             }
+
+            public void Dispose()
+            {
+            }
         }

         private class TestLogger : ILogger


Tighten up test

Tighten up test

--- test/Steeltoe.Discovery.Eureka.Client.Test/Task/TimedTaskTest.cs
+++ test/Steeltoe.Discovery.Eureka.Client.Test/Task/TimedTaskTest.cs
@@ -27,7 +27,7 @@
         {
             _timerFuncCount = 0;
             var timedTask = new TimedTask("MyTask", TimerFunc);
-            var timer = new Timer(timedTask.Run, null, 100, 100);
+            var timer = new Timer(timedTask.Run, null, 10, 100);
             System.Threading.Thread.Sleep(1000);
             Assert.Equal(1, _timerFuncCount);

@@ -35,7 +35,7 @@
         }

-        private int _timerFuncCount;
+        private volatile int _timerFuncCount;
         public void TimerFunc()
         {
             ++_timerFuncCount;


(build) publishing nuget packages only when building for gittools/gitversion repo

--- build/publish.cake
+++ build/publish.cake
@@ -57,7 +57,7 @@
     .IsDependentOnWhen("Pack-NuGet", singleStageRun)
     .Does<BuildParameters>((parameters) =>
 {
-    if (parameters.IsStableRelease())
+    if (parameters.IsStableRelease())
     {
         var apiKey = parameters.Credentials.Nuget.ApiKey;
         if(string.IsNullOrEmpty(apiKey)) {
@@ -84,7 +84,7 @@
     }

     // Push the package to GitHub Packages
-    if (parameters.IsRunningOnGitHubActions)
+    if (parameters.IsRunningOnGitHubActions && parameters.IsMainRepo && parameters.IsMainBranch)
     {
         Information("Publishing nuget to GitHub Packages");


(Seraph): mark compressed entries.

(Seraph): mark compressed entries.


Added unit test for Bug #3414862

Added unit test for Bug #3414862


Adjust handling the binaries in docsmashup module based on the latest changes in dxa framework

--- webapp-net/TridionDocsMashup/Controllers/TridionDocsMashupController.cs
+++ webapp-net/TridionDocsMashup/Controllers/TridionDocsMashupController.cs
@@ -9,8 +9,8 @@
 using System.Web.Mvc;
 using Sdl.Web.Mvc.Formats;
 using System;
-using Sdl.Web.Tridion.TridionDocs.Providers;
 using Sdl.Web.Common.Logging;
+using Sdl.Web.Tridion.TridionDocs.Localization;

 namespace Sdl.Web.Modules.TridionDocsMashup.Controllers
 {
@@ -78,7 +78,8 @@
         {
             try
             {
-                StaticContentItem content = DocsContentProvider.GetStaticContentItem(publicationId, binaryId);
+                var docsLocalization = new DocsLocalization { Id = publicationId.ToString() };
+                StaticContentItem content = ContentProvider.GetStaticContentItem(binaryId, docsLocalization);
                 return new FileStreamResult(content.GetContentStream(), content.ContentType);
             }
             catch (Exception ex)


Use local for performance

Use local for performance

--- osu.Framework/Graphics/Transforms/Transformable.cs
+++ osu.Framework/Graphics/Transforms/Transformable.cs
@@ -286,7 +286,9 @@

             Transforms.Add(transform);

-            if (Transforms.LastOrDefault(t => t.StartTime <= Time.Current && t.GetType() == transform.GetType()) == transform)
+            var transformType = transform.GetType();
+
+            if (Transforms.LastOrDefault(t => t.StartTime <= Time.Current && t.GetType() == transformType) == transform)
             {
                 transform.UpdateTime(new FrameTimeInfo { Current = Time.Current });
                 transform.ReadIntoStartValue(derivedThis);


Fix ArgumentException warnings

Fix ArgumentException warnings

--- osu.Framework/Platform/Windows/Native/IconGroup.cs
+++ osu.Framework/Platform/Windows/Native/IconGroup.cs
@@ -58,7 +58,7 @@
         public IconGroup(Stream stream)
         {
             if (stream == null || stream.Length == 0)
-                throw new ArgumentException("Invalid icon stream.", nameof(stream));
+                throw new ArgumentException("Missing icon stream.", nameof(stream));

             using (var ms = new MemoryStream())
             {
@@ -70,7 +70,7 @@
         public IconGroup(byte[] data)
         {
             if (data == null || data.Length == 0)
-                throw new ArgumentException("Invalid icon data.", nameof(data));
+                throw new ArgumentException("Missing icon data.", nameof(data));

             using (var ms = new MemoryStream(data))
                 loadMemoryStream(ms);
@@ -84,11 +84,11 @@
             var reader = new BinaryReader(stream);
             iconDir.Reserved = reader.ReadUInt16();
             if (iconDir.Reserved != 0)
-                throw new ArgumentException("Invalid icon data.", nameof(data));
+                throw new ArgumentException("Invalid icon format.", nameof(stream));

             iconDir.Type = reader.ReadUInt16();
             if (iconDir.Type != 1)
-                throw new ArgumentException("Invalid icon data.", nameof(data));
+                throw new ArgumentException("Invalid icon format.", nameof(stream));

             iconDir.Count = reader.ReadUInt16();
             iconDir.Entries = new IconDirEntry[iconDir.Count];


Fix scoreV2 being higher than intended

Fix scoreV2 being higher than intended

--- osu.Game.Tests/Visual/Gameplay/TestSceneScoring.cs
+++ osu.Game.Tests/Visual/Gameplay/TestSceneScoring.cs
@@ -167,14 +167,12 @@

         private void runScoreV2()
         {
+            int maxCombo = sliderMaxCombo.Current.Value;
+
             int currentCombo = 0;
             double comboPortion = 0;
-
-            int maxCombo = sliderMaxCombo.Current.Value;
-
             double currentBaseScore = 0;
             double maxBaseScore = 0;
-
             int currentHits = 0;

             for (int i = 0; i < maxCombo; i++)
@@ -182,9 +180,10 @@

             double comboPortionMax = comboPortion;

+            currentCombo = 0;
             comboPortion = 0;
+            currentBaseScore = 0;
             maxBaseScore = 0;
-            currentBaseScore = 0;
             currentHits = 0;

             void applyHitV2(int baseScore)


Fix `RulesetSkinProvidingContainer` potentially late in setting up skin sources

--- osu.Game/Skinning/RulesetSkinProvidingContainer.cs
+++ osu.Game/Skinning/RulesetSkinProvidingContainer.cs
@@ -42,27 +42,30 @@
             };
         }

-        [Resolved]
-        private ISkinSource skinSource { get; set; }
+        private ISkinSource parentSource;

-        [BackgroundDependencyLoader]
-        private void load()
+        protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent)
         {
-            UpdateSkins();
-            skinSource.SourceChanged += OnSourceChanged;
+            parentSource = parent.Get<ISkinSource>();
+
+            UpdateSkinSources();
+
+            parentSource.SourceChanged += OnSourceChanged;
+
+            return base.CreateChildDependencies(parent);
         }

         protected override void OnSourceChanged()
         {
-            UpdateSkins();
+            UpdateSkinSources();
             base.OnSourceChanged();
         }

-        protected virtual void UpdateSkins()
+        protected virtual void UpdateSkinSources()
         {
             SkinSources.Clear();

-            foreach (var skin in skinSource.AllSources)
+            foreach (var skin in parentSource.AllSources)
             {
                 switch (skin)
                 {
@@ -93,8 +96,8 @@
         {
             base.Dispose(isDisposing);

-            if (skinSource != null)
-                skinSource.SourceChanged -= OnSourceChanged;
+            if (parentSource != null)
+                parentSource.SourceChanged -= OnSourceChanged;
         }
     }
 }


Make `getRulesetTransformedSkin` private

--- osu.Game/Skinning/RulesetSkinProvidingContainer.cs
+++ osu.Game/Skinning/RulesetSkinProvidingContainer.cs
@@ -26,7 +26,7 @@
             Ruleset = ruleset;
             Beatmap = beatmap;

-            InternalChild = new BeatmapSkinProvidingContainer(GetRulesetTransformedSkin(beatmapSkin))
+            InternalChild = new BeatmapSkinProvidingContainer(getRulesetTransformedSkin(beatmapSkin))
             {
                 Child = Content = new Container
                 {
@@ -54,17 +54,17 @@
         {
             SkinSources.Clear();

-            SkinSources.Add(GetRulesetTransformedSkin(skinManager.CurrentSkin.Value));
+            SkinSources.Add(getRulesetTransformedSkin(skinManager.CurrentSkin.Value));

             // TODO: we also want to return a DefaultLegacySkin here if the current *beatmap* is providing any skinned elements.
             if (skinManager.CurrentSkin.Value is LegacySkin && skinManager.CurrentSkin.Value != skinManager.DefaultLegacySkin)
-                SkinSources.Add(GetRulesetTransformedSkin(skinManager.DefaultLegacySkin));
+                SkinSources.Add(getRulesetTransformedSkin(skinManager.DefaultLegacySkin));

             if (skinManager.CurrentSkin.Value != skinManager.DefaultSkin)
-                SkinSources.Add(GetRulesetTransformedSkin(skinManager.DefaultSkin));
+                SkinSources.Add(getRulesetTransformedSkin(skinManager.DefaultSkin));
         }

-        protected ISkin GetRulesetTransformedSkin(ISkin skin)
+        private ISkin getRulesetTransformedSkin(ISkin skin)
         {
             if (skin == null)
                 return null;


Modify "http.uri" to "http.url"

Modify "http.uri" to "http.url"

--- zipkin4net-owin/Criteo.Profiling.Tracing.Middleware/ZipkinMiddleware.cs
+++ zipkin4net-owin/Criteo.Profiling.Tracing.Middleware/ZipkinMiddleware.cs
@@ -32,7 +32,7 @@
             using (var serverTrace = new ServerTrace(this.serviceName, context.Request.Method))
             {
                 trace.Record(Annotations.Tag("http.host", context.Request.Host.Value));
-                trace.Record(Annotations.Tag("http.uri", context.Request.Uri.AbsoluteUri));
+                trace.Record(Annotations.Tag("http.url", context.Request.Uri.AbsoluteUri));
                 trace.Record(Annotations.Tag("http.path", context.Request.Uri.AbsolutePath));

                 await serverTrace.TracedActionAsync(Next.Invoke(context));