diff --git a/shadowsocks-csharp/Controller/Service/AvailabilityStatistics.cs b/shadowsocks-csharp/Controller/Service/AvailabilityStatistics.cs index f547af10..790f5d1b 100644 --- a/shadowsocks-csharp/Controller/Service/AvailabilityStatistics.cs +++ b/shadowsocks-csharp/Controller/Service/AvailabilityStatistics.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Concurrent; using System.Collections.Generic; using System.IO; using System.Linq; @@ -31,12 +32,14 @@ namespace Shadowsocks.Controller public const int TimeoutMilliseconds = 500; //records cache for current server in {_monitorInterval} minutes - private List _latencyRecords; + private readonly ConcurrentDictionary> _latencyRecords = new ConcurrentDictionary>(); //speed in KiB/s - private long _lastInboundCounter; - private List _inboundSpeedRecords; - private long _lastOutboundCounter; - private List _outboundSpeedRecords; + private readonly ConcurrentDictionary _inboundCounter = new ConcurrentDictionary(); + private readonly ConcurrentDictionary _lastInboundCounter = new ConcurrentDictionary(); + private readonly ConcurrentDictionary> _inboundSpeedRecords = new ConcurrentDictionary>(); + private readonly ConcurrentDictionary _outboundCounter = new ConcurrentDictionary(); + private readonly ConcurrentDictionary _lastOutboundCounter = new ConcurrentDictionary(); + private readonly ConcurrentDictionary> _outboundSpeedRecords = new ConcurrentDictionary>(); //tasks private readonly TimeSpan _delayBeforeStart = TimeSpan.FromSeconds(1); @@ -45,12 +48,11 @@ namespace Shadowsocks.Controller private TimeSpan RecordingInterval => TimeSpan.FromMinutes(Config.DataCollectionMinutes); private Timer _speedMonior; private readonly TimeSpan _monitorInterval = TimeSpan.FromSeconds(1); - private Timer _writer; //write RawStatistics to file - private readonly TimeSpan _writingInterval = TimeSpan.FromMinutes(1); + //private Timer _writer; //write RawStatistics to file + //private readonly TimeSpan _writingInterval = TimeSpan.FromMinutes(1); private ShadowsocksController _controller; private StatisticsStrategyConfiguration Config => _controller.StatisticsConfiguration; - private Server CurrentServer => _controller.GetCurrentServer(); // Static Singleton Initialization public static AvailabilityStatistics Instance { get; } = new AvailabilityStatistics(); @@ -73,13 +75,11 @@ namespace Shadowsocks.Controller StartTimerWithoutState(ref _recorder, Run, RecordingInterval); LoadRawStatistics(); StartTimerWithoutState(ref _speedMonior, UpdateSpeed, _monitorInterval); - StartTimerWithoutState(ref _writer, Save, _writingInterval); } else { _recorder?.Dispose(); _speedMonior?.Dispose(); - _writer?.Dispose(); } } catch (Exception e) @@ -98,18 +98,27 @@ namespace Shadowsocks.Controller private void UpdateSpeed(object _) { - var bytes = _controller.inboundCounter - _lastInboundCounter; - _lastInboundCounter = _controller.inboundCounter; - var inboundSpeed = GetSpeedInKiBPerSecond(bytes, _monitorInterval.TotalSeconds); - _inboundSpeedRecords.Add(inboundSpeed); - - bytes = _controller.outboundCounter - _lastOutboundCounter; - _lastOutboundCounter = _controller.outboundCounter; - var outboundSpeed = GetSpeedInKiBPerSecond(bytes, _monitorInterval.TotalSeconds); - _outboundSpeedRecords.Add(outboundSpeed); - - Logging.Debug( - $"{CurrentServer.FriendlyName()}: current/max inbound {inboundSpeed}/{_inboundSpeedRecords.Max()} KiB/s, current/max outbound {outboundSpeed}/{_outboundSpeedRecords.Max()} KiB/s"); + foreach (var kv in _lastInboundCounter) + { + var id = kv.Key; + + var lastInbound = kv.Value; + var inbound = _inboundCounter[id]; + var bytes = inbound - lastInbound; + _lastInboundCounter[id] = inbound; + var inboundSpeed = GetSpeedInKiBPerSecond(bytes, _monitorInterval.TotalSeconds); + _inboundSpeedRecords.GetOrAdd(id, new List {inboundSpeed}).Add(inboundSpeed); + + var lastOutbound = _lastOutboundCounter[id]; + var outbound = _outboundCounter[id]; + bytes = outbound - lastOutbound; + _lastOutboundCounter[id] = outbound; + var outboundSpeed = GetSpeedInKiBPerSecond(bytes, _monitorInterval.TotalSeconds); + _outboundSpeedRecords.GetOrAdd(id, new List {outboundSpeed}).Add(outboundSpeed); + + Logging.Debug( + $"{id}: current/max inbound {inboundSpeed}/{_inboundSpeedRecords[id].Max()} KiB/s, current/max outbound {outboundSpeed}/{_outboundSpeedRecords[id].Max()} KiB/s"); + } } private async Task ICMPTest(Server server) @@ -161,66 +170,75 @@ namespace Shadowsocks.Controller private void Reset() { - _inboundSpeedRecords = new List(); - _outboundSpeedRecords = new List(); - _latencyRecords = new List(); + _inboundSpeedRecords.Clear(); + _outboundSpeedRecords.Clear(); + _latencyRecords.Clear(); } private void Run(object _) { UpdateRecords(); + Save(); Reset(); FilterRawStatistics(); } private async void UpdateRecords() { - var currentServerRecord = new StatisticsRecord(CurrentServer.Identifier(), _inboundSpeedRecords, _outboundSpeedRecords, _latencyRecords); + var records = new Dictionary(); - if (!Config.Ping) + foreach (var server in _controller.GetCurrentConfiguration().configs) { - AppendRecord(CurrentServer, currentServerRecord); - return; + var id = server.Identifier(); + List inboundSpeedRecords = null; + List outboundSpeedRecords = null; + List latencyRecords = null; + _inboundSpeedRecords.TryGetValue(id, out inboundSpeedRecords); + _outboundSpeedRecords.TryGetValue(id, out outboundSpeedRecords); + _latencyRecords.TryGetValue(id, out latencyRecords); + records.Add(id, new StatisticsRecord(id, inboundSpeedRecords, outboundSpeedRecords, latencyRecords)); } - var icmpResults = TaskEx.WhenAll(_controller.GetCurrentConfiguration().configs.Select(ICMPTest)); - - foreach (var result in (await icmpResults).Where(result => result != null)) + if (Config.Ping) { - if (result.Server.Equals(CurrentServer)) + var icmpResults = await TaskEx.WhenAll(_controller.GetCurrentConfiguration().configs.Select(ICMPTest)); + foreach (var result in icmpResults.Where(result => result != null)) { - currentServerRecord.setResponse(result.RoundtripTime); - AppendRecord(CurrentServer, currentServerRecord); - } - else - { - AppendRecord(result.Server, new StatisticsRecord(result.Server.Identifier(), result.RoundtripTime)); + records[result.Server.Identifier()].SetResponse(result.RoundtripTime); } } + + foreach (var kv in records.Where(kv => !kv.Value.IsEmptyData())) + { + AppendRecord(kv.Key, kv.Value); + } } - private void AppendRecord(Server server, StatisticsRecord record) + private void AppendRecord(string serverIdentifier, StatisticsRecord record) { List records; - if (!RawStatistics.TryGetValue(server.Identifier(), out records)) + if (!RawStatistics.TryGetValue(serverIdentifier, out records)) { records = new List(); } records.Add(record); - RawStatistics[server.Identifier()] = records; + RawStatistics[serverIdentifier] = records; } - private void Save(object _) + private void Save() { + if (RawStatistics.Count == 0) + { + return; + } try { - File.WriteAllText(AvailabilityStatisticsFile, - JsonConvert.SerializeObject(RawStatistics, Formatting.None)); + var content = JsonConvert.SerializeObject(RawStatistics, Formatting.None); + File.WriteAllText(AvailabilityStatisticsFile, content); } catch (IOException e) { Logging.LogUsefulException(e); - _writer.Change(_retryInterval, _writingInterval); } } @@ -273,11 +291,6 @@ namespace Shadowsocks.Controller } } - public void UpdateLatency(int latency) - { - _latencyRecords.Add(latency); - } - private static int GetSpeedInKiBPerSecond(long bytes, double seconds) { var result = (int) (bytes/seconds)/1024; @@ -298,8 +311,49 @@ namespace Shadowsocks.Controller public void Dispose() { _recorder.Dispose(); - _writer.Dispose(); _speedMonior.Dispose(); } + + public void UpdateLatency(Server server, int latency) + { + List records; + _latencyRecords.TryGetValue(server.Identifier(), out records); + if (records == null) + { + records = new List(); + } + records.Add(latency); + _latencyRecords[server.Identifier()] = records; + } + + public void UpdateInboundCounter(Server server, long n) + { + long count; + if (_inboundCounter.TryGetValue(server.Identifier(), out count)) + { + count += n; + } + else + { + count = n; + _lastInboundCounter[server.Identifier()] = 0; + } + _inboundCounter[server.Identifier()] = count; + } + + public void UpdateOutboundCounter(Server server, long n) + { + long count; + if (_outboundCounter.TryGetValue(server.Identifier(), out count)) + { + count += n; + } + else + { + count = n; + _lastOutboundCounter[server.Identifier()] = 0; + } + _outboundCounter[server.Identifier()] = count; + } } } diff --git a/shadowsocks-csharp/Controller/Service/TCPRelay.cs b/shadowsocks-csharp/Controller/Service/TCPRelay.cs index d5d82ed5..9c162780 100644 --- a/shadowsocks-csharp/Controller/Service/TCPRelay.cs +++ b/shadowsocks-csharp/Controller/Service/TCPRelay.cs @@ -69,14 +69,14 @@ namespace Shadowsocks.Controller return true; } - public void UpdateInboundCounter(long n) + public void UpdateInboundCounter(Server server, long n) { - _controller.UpdateInboundCounter(n); + _controller.UpdateInboundCounter(server, n); } - public void UpdateOutboundCounter(long n) + public void UpdateOutboundCounter(Server server, long n) { - _controller.UpdateOutboundCounter(n); + _controller.UpdateOutboundCounter(server, n); } public void UpdateLatency(Server server, TimeSpan latency) @@ -488,10 +488,7 @@ namespace Shadowsocks.Controller var latency = DateTime.Now - _startConnectTime; IStrategy strategy = controller.GetCurrentStrategy(); - if (strategy != null) - { - strategy.UpdateLatency(server, latency); - } + strategy?.UpdateLatency(server, latency); tcprelay.UpdateLatency(server, latency); StartPipe(); @@ -543,7 +540,7 @@ namespace Shadowsocks.Controller { int bytesRead = remote.EndReceive(ar); totalRead += bytesRead; - tcprelay.UpdateInboundCounter(bytesRead); + tcprelay.UpdateInboundCounter(server, bytesRead); if (bytesRead > 0) { @@ -610,7 +607,7 @@ namespace Shadowsocks.Controller encryptor.Encrypt(connetionRecvBuffer, bytesRead, connetionSendBuffer, out bytesToSend); } Logging.Debug(remote, bytesToSend, "TCP Relay", "@PipeConnectionReceiveCallback() (upload)"); - tcprelay.UpdateOutboundCounter(bytesToSend); + tcprelay.UpdateOutboundCounter(server, bytesToSend); _startSendingTime = DateTime.Now; _bytesToSend = bytesToSend; remote.BeginSend(connetionSendBuffer, 0, bytesToSend, 0, new AsyncCallback(PipeRemoteSendCallback), null); diff --git a/shadowsocks-csharp/Controller/ShadowsocksController.cs b/shadowsocks-csharp/Controller/ShadowsocksController.cs index cb49f5f2..13c6650d 100755 --- a/shadowsocks-csharp/Controller/ShadowsocksController.cs +++ b/shadowsocks-csharp/Controller/ShadowsocksController.cs @@ -5,7 +5,7 @@ using System.Net; using System.Net.Sockets; using System.Text; using System.Threading; - +using System.Threading.Tasks; using Newtonsoft.Json; using Shadowsocks.Controller.Strategy; @@ -307,14 +307,30 @@ namespace Shadowsocks.Controller Configuration.Save(_config); } - public void UpdateInboundCounter(long n) + public void UpdateLatency(Server server, TimeSpan latency) + { + if (_config.availabilityStatistics) + { + new Task(() => availabilityStatistics.UpdateLatency(server, (int) latency.TotalMilliseconds)).Start(); + } + } + + public void UpdateInboundCounter(Server server, long n) { Interlocked.Add(ref inboundCounter, n); + if (_config.availabilityStatistics) + { + new Task(() => availabilityStatistics.UpdateInboundCounter(server, n)).Start(); + } } - public void UpdateOutboundCounter(long n) + public void UpdateOutboundCounter(Server server, long n) { Interlocked.Add(ref outboundCounter, n); + if (_config.availabilityStatistics) + { + new Task(() => availabilityStatistics.UpdateOutboundCounter(server, n)).Start(); + } } protected void Reload() @@ -498,12 +514,5 @@ namespace Shadowsocks.Controller } } - public void UpdateLatency(Server server, TimeSpan latency) - { - if (_config.availabilityStatistics) - { - availabilityStatistics.UpdateLatency((int) latency.TotalMilliseconds); - } - } } } diff --git a/shadowsocks-csharp/Controller/Strategy/StatisticsStrategy.cs b/shadowsocks-csharp/Controller/Strategy/StatisticsStrategy.cs index 261ef909..075e18e4 100644 --- a/shadowsocks-csharp/Controller/Strategy/StatisticsStrategy.cs +++ b/shadowsocks-csharp/Controller/Strategy/StatisticsStrategy.cs @@ -49,29 +49,32 @@ namespace Shadowsocks.Controller.Strategy //return the score by data //server with highest score will be choosen - private float GetScore(string serverName) + private float? GetScore(string identifier, List records) { var config = _controller.StatisticsConfiguration; - List records; - if (_filteredStatistics == null || !_filteredStatistics.TryGetValue(serverName, out records)) return 0; - float factor; - float score = 0; - - var averageRecord = new StatisticsRecord(serverName, - records.FindAll(record => record.MaxInboundSpeed != null).Select(record => record.MaxInboundSpeed.Value), - records.FindAll(record => record.MaxOutboundSpeed != null).Select(record => record.MaxOutboundSpeed.Value), - records.FindAll(record => record.AverageLatency != null).Select(record => record.AverageLatency.Value)); - averageRecord.setResponse(records.Select(record => record.AverageResponse)); - - if (!config.Calculations.TryGetValue("PackageLoss", out factor)) factor = 0; - score += averageRecord.PackageLoss * factor ?? 0; - if (!config.Calculations.TryGetValue("AverageResponse", out factor)) factor = 0; - score += averageRecord.AverageResponse * factor ?? 0; - if (!config.Calculations.TryGetValue("MinResponse", out factor)) factor = 0; - score += averageRecord.MinResponse * factor ?? 0; - if (!config.Calculations.TryGetValue("MaxResponse", out factor)) factor = 0; - score += averageRecord.MaxResponse * factor ?? 0; - Logging.Debug($"Highest score: {score} {JsonConvert.SerializeObject(averageRecord, Formatting.Indented)}"); + float? score = null; + + var averageRecord = new StatisticsRecord(identifier, + records.Where(record => record.MaxInboundSpeed != null).Select(record => record.MaxInboundSpeed.Value).ToList(), + records.Where(record => record.MaxOutboundSpeed != null).Select(record => record.MaxOutboundSpeed.Value).ToList(), + records.Where(record => record.AverageLatency != null).Select(record => record.AverageLatency.Value).ToList()); + averageRecord.SetResponse(records.Select(record => record.AverageResponse).ToList()); + + foreach (var calculation in config.Calculations) + { + var name = calculation.Key; + var field = typeof (StatisticsRecord).GetField(name); + dynamic value = field.GetValue(averageRecord); + var factor = calculation.Value; + if (value == null || factor.Equals(0)) continue; + score = score ?? 0; + score += value * factor; + } + + if (score != null) + { + Logging.Debug($"Highest score: {score} {JsonConvert.SerializeObject(averageRecord, Formatting.Indented)}"); + } return score; } @@ -83,15 +86,25 @@ namespace Shadowsocks.Controller.Strategy } try { - var bestResult = (from server in servers - let name = server.FriendlyName() - where _filteredStatistics.ContainsKey(name) - select new - { - server, - score = GetScore(name) - } - ).Aggregate((result1, result2) => result1.score > result2.score ? result1 : result2); + var serversWithStatistics = (from server in servers + let id = server.Identifier() + where _filteredStatistics.ContainsKey(id) + let score = GetScore(server.Identifier(), _filteredStatistics[server.Identifier()]) + where score != null + select new + { + server, + score + }).ToArray(); + + if (serversWithStatistics.Length < 2) + { + LogWhenEnabled("no enough statistics data for evaluation"); + return; + } + + var bestResult = serversWithStatistics + .Aggregate((server1, server2) => server1.score > server2.score ? server1 : server2); LogWhenEnabled($"Switch to server: {bestResult.server.FriendlyName()} by statistics: score {bestResult.score}"); _currentServer = bestResult.server; @@ -112,7 +125,7 @@ namespace Shadowsocks.Controller.Strategy public string ID => "com.shadowsocks.strategy.scbs"; - public string Name => I18N.GetString("Choose By Total Package Loss"); + public string Name => I18N.GetString("Choose by statistics"); public Server GetAServer(IStrategyCallerType type, IPEndPoint localIPEndPoint) { diff --git a/shadowsocks-csharp/Data/cn.txt b/shadowsocks-csharp/Data/cn.txt index a6d77156..68af293b 100644 --- a/shadowsocks-csharp/Data/cn.txt +++ b/shadowsocks-csharp/Data/cn.txt @@ -30,7 +30,7 @@ Quit=退出 Edit Servers=编辑服务器 Load Balance=负载均衡 High Availability=高可用 -Choose By Total Package Loss=累计丢包率 +Choose by statistics=根据统计 # Config Form diff --git a/shadowsocks-csharp/Model/StatisticsRecord.cs b/shadowsocks-csharp/Model/StatisticsRecord.cs index 545aa3a9..47015f75 100644 --- a/shadowsocks-csharp/Model/StatisticsRecord.cs +++ b/shadowsocks-csharp/Model/StatisticsRecord.cs @@ -9,34 +9,49 @@ namespace Shadowsocks.Model public class StatisticsRecord { public DateTime Timestamp { get; set; } = DateTime.Now; - public string ServerName { get; set; } + public string ServerIdentifier { get; set; } // in ping-only records, these fields would be null public int? AverageLatency; public int? MinLatency; public int? MaxLatency; + private bool EmptyLatencyData => (AverageLatency == null) && (MinLatency == null) && (MaxLatency == null); + public int? AverageInboundSpeed; public int? MinInboundSpeed; public int? MaxInboundSpeed; + private bool EmptyInboundSpeedData + => (AverageInboundSpeed == null) && (MinInboundSpeed == null) && (MaxInboundSpeed == null); + public int? AverageOutboundSpeed; public int? MinOutboundSpeed; public int? MaxOutboundSpeed; + private bool EmptyOutboundSpeedData + => (AverageOutboundSpeed == null) && (MinOutboundSpeed == null) && (MaxOutboundSpeed == null); + // if user disabled ping test, response would be null public int? AverageResponse; public int? MinResponse; public int? MaxResponse; public float? PackageLoss; + private bool EmptyResponseData + => (AverageResponse == null) && (MinResponse == null) && (MaxResponse == null) && (PackageLoss == null); + + public bool IsEmptyData() { + return EmptyInboundSpeedData && EmptyOutboundSpeedData && EmptyResponseData && EmptyLatencyData; + } + public StatisticsRecord() { } - public StatisticsRecord(string identifier, IEnumerable inboundSpeedRecords, IEnumerable outboundSpeedRecords, IEnumerable latencyRecords) + public StatisticsRecord(string identifier, ICollection inboundSpeedRecords, ICollection outboundSpeedRecords, ICollection latencyRecords) { - ServerName = identifier; + ServerIdentifier = identifier; if (inboundSpeedRecords != null && inboundSpeedRecords.Any()) { AverageInboundSpeed = (int) inboundSpeedRecords.Average(); @@ -57,13 +72,13 @@ namespace Shadowsocks.Model } } - public StatisticsRecord(string identifier, IEnumerable responseRecords) + public StatisticsRecord(string identifier, ICollection responseRecords) { - ServerName = identifier; - setResponse(responseRecords); + ServerIdentifier = identifier; + SetResponse(responseRecords); } - public void setResponse(IEnumerable responseRecords) + public void SetResponse(ICollection responseRecords) { if (responseRecords == null) return; var records = responseRecords.Where(response => response != null).Select(response => response.Value).ToList(); @@ -71,7 +86,7 @@ namespace Shadowsocks.Model AverageResponse = (int?) records.Average(); MinResponse = records.Min(); MaxResponse = records.Max(); - PackageLoss = responseRecords.Count(response => response != null)/(float) responseRecords.Count(); + PackageLoss = responseRecords.Count(response => response != null)/(float) responseRecords.Count; } } } diff --git a/shadowsocks-csharp/View/StatisticsStrategyConfigurationForm.Designer.cs b/shadowsocks-csharp/View/StatisticsStrategyConfigurationForm.Designer.cs index 274f93b0..19cc6731 100644 --- a/shadowsocks-csharp/View/StatisticsStrategyConfigurationForm.Designer.cs +++ b/shadowsocks-csharp/View/StatisticsStrategyConfigurationForm.Designer.cs @@ -36,6 +36,7 @@ System.Windows.Forms.DataVisualization.Charting.Series series3 = new System.Windows.Forms.DataVisualization.Charting.Series(); this.StatisticsChart = new System.Windows.Forms.DataVisualization.Charting.Chart(); this.PingCheckBox = new System.Windows.Forms.CheckBox(); + this.bindingConfiguration = new System.Windows.Forms.BindingSource(this.components); this.label2 = new System.Windows.Forms.Label(); this.label3 = new System.Windows.Forms.Label(); this.chartModeSelector = new System.Windows.Forms.GroupBox(); @@ -58,8 +59,8 @@ this.CancelButton = new System.Windows.Forms.Button(); this.OKButton = new System.Windows.Forms.Button(); this.CalculatinTip = new System.Windows.Forms.ToolTip(this.components); - this.bindingConfiguration = new System.Windows.Forms.BindingSource(this.components); ((System.ComponentModel.ISupportInitialize)(this.StatisticsChart)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.bindingConfiguration)).BeginInit(); this.chartModeSelector.SuspendLayout(); ((System.ComponentModel.ISupportInitialize)(this.splitContainer1)).BeginInit(); this.splitContainer1.Panel1.SuspendLayout(); @@ -76,7 +77,6 @@ this.splitContainer3.Panel1.SuspendLayout(); this.splitContainer3.Panel2.SuspendLayout(); this.splitContainer3.SuspendLayout(); - ((System.ComponentModel.ISupportInitialize)(this.bindingConfiguration)).BeginInit(); this.SuspendLayout(); // // StatisticsChart @@ -142,6 +142,10 @@ this.PingCheckBox.UseVisualStyleBackColor = true; this.PingCheckBox.CheckedChanged += new System.EventHandler(this.PingCheckBox_CheckedChanged); // + // bindingConfiguration + // + this.bindingConfiguration.DataSource = typeof(Shadowsocks.Model.StatisticsStrategyConfiguration); + // // label2 // this.label2.AutoSize = true; @@ -167,7 +171,7 @@ this.chartModeSelector.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); this.chartModeSelector.Controls.Add(this.allMode); this.chartModeSelector.Controls.Add(this.dayMode); - this.chartModeSelector.Location = new System.Drawing.Point(729, 194); + this.chartModeSelector.Location = new System.Drawing.Point(729, 188); this.chartModeSelector.Margin = new System.Windows.Forms.Padding(5, 10, 5, 10); this.chartModeSelector.Name = "chartModeSelector"; this.chartModeSelector.Padding = new System.Windows.Forms.Padding(5, 10, 5, 10); @@ -437,7 +441,7 @@ // this.serverSelector.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); this.serverSelector.FormattingEnabled = true; - this.serverSelector.Location = new System.Drawing.Point(729, 157); + this.serverSelector.Location = new System.Drawing.Point(729, 151); this.serverSelector.Name = "serverSelector"; this.serverSelector.Size = new System.Drawing.Size(233, 35); this.serverSelector.TabIndex = 6; @@ -446,7 +450,7 @@ // CancelButton // this.CancelButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); - this.CancelButton.Location = new System.Drawing.Point(861, 376); + this.CancelButton.Location = new System.Drawing.Point(861, 370); this.CancelButton.Name = "CancelButton"; this.CancelButton.Size = new System.Drawing.Size(101, 41); this.CancelButton.TabIndex = 5; @@ -457,7 +461,7 @@ // OKButton // this.OKButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); - this.OKButton.Location = new System.Drawing.Point(754, 376); + this.OKButton.Location = new System.Drawing.Point(754, 370); this.OKButton.Name = "OKButton"; this.OKButton.Size = new System.Drawing.Size(101, 41); this.OKButton.TabIndex = 4; @@ -465,12 +469,6 @@ this.OKButton.UseVisualStyleBackColor = true; this.OKButton.Click += new System.EventHandler(this.OKButton_Click); // - // bindingConfiguration - // - this.bindingConfiguration.DataSource = typeof(Shadowsocks.Model.StatisticsStrategyConfiguration); - this.bindingConfiguration.BindingComplete += new System.Windows.Forms.BindingCompleteEventHandler(this.bindingConfiguration_BindingComplete); - this.bindingConfiguration.CurrentItemChanged += new System.EventHandler(this.bindingConfiguration_CurrentItemChanged); - // // StatisticsStrategyConfigurationForm // this.AutoScaleDimensions = new System.Drawing.SizeF(12F, 27F); @@ -484,6 +482,7 @@ this.Name = "StatisticsStrategyConfigurationForm"; this.Text = "StatisticsStrategyConfigurationForm"; ((System.ComponentModel.ISupportInitialize)(this.StatisticsChart)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.bindingConfiguration)).EndInit(); this.chartModeSelector.ResumeLayout(false); this.chartModeSelector.PerformLayout(); this.splitContainer1.Panel1.ResumeLayout(false); @@ -503,7 +502,6 @@ this.splitContainer3.Panel2.ResumeLayout(false); ((System.ComponentModel.ISupportInitialize)(this.splitContainer3)).EndInit(); this.splitContainer3.ResumeLayout(false); - ((System.ComponentModel.ISupportInitialize)(this.bindingConfiguration)).EndInit(); this.ResumeLayout(false); } diff --git a/shadowsocks-csharp/View/StatisticsStrategyConfigurationForm.cs b/shadowsocks-csharp/View/StatisticsStrategyConfigurationForm.cs index 9fec183d..42f8ee87 100644 --- a/shadowsocks-csharp/View/StatisticsStrategyConfigurationForm.cs +++ b/shadowsocks-csharp/View/StatisticsStrategyConfigurationForm.cs @@ -36,7 +36,7 @@ namespace Shadowsocks.View private void LoadConfiguration() { var configs = _controller.GetCurrentConfiguration().configs; - _servers = configs.Select(server => server.FriendlyName()).ToList(); + _servers = configs.Select(server => server.Identifier()).ToList(); _configuration = _controller.StatisticsConfiguration ?? new StatisticsStrategyConfiguration(); if (_configuration.Calculations == null) @@ -153,15 +153,5 @@ namespace Shadowsocks.View { repeatTimesNum.ReadOnly = !PingCheckBox.Checked; } - - private void bindingConfiguration_CurrentItemChanged(object sender, EventArgs e) - { - Logging.Info("?"); - } - - private void bindingConfiguration_BindingComplete(object sender, BindingCompleteEventArgs e) - { - Logging.Info("?"); - } } } diff --git a/shadowsocks-csharp/View/StatisticsStrategyConfigurationForm.resx b/shadowsocks-csharp/View/StatisticsStrategyConfigurationForm.resx index 446dcc01..8360b4c2 100644 --- a/shadowsocks-csharp/View/StatisticsStrategyConfigurationForm.resx +++ b/shadowsocks-csharp/View/StatisticsStrategyConfigurationForm.resx @@ -118,12 +118,12 @@ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - 1, 30 + 4, 5 238, 6 - 37 + 191 \ No newline at end of file diff --git a/shadowsocks-csharp/shadowsocks-csharp.csproj b/shadowsocks-csharp/shadowsocks-csharp.csproj index 101ad9ee..d186471e 100644 --- a/shadowsocks-csharp/shadowsocks-csharp.csproj +++ b/shadowsocks-csharp/shadowsocks-csharp.csproj @@ -53,13 +53,14 @@ bin\x86\Release\ TRACE - true + false pdbonly x86 prompt ManagedMinimumRules.ruleset false true + true app.manifest @@ -341,13 +342,12 @@ - - - - - - - + + + + + f.ItemSpec).Where(f => !excludedAssemblie foreach (var item in filesToCleanup) File.Delete(item); -]]> - +]]> +