Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove file system watcher #99

Merged
merged 1 commit into from
Sep 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -54,10 +54,10 @@ public class CommandLineSettings
public string Signature { get; set; }

[Option(CommandOptionType.SingleValue, ShortName = "x", Description = "Azure Relay connection string (overridden with -S -K -k -e)")]
public string ConnectionString { get; internal set; }
public string ConnectionString { get; set; }

[Option(CommandOptionType.NoValue, ShortName = "v", Description = "Verbose log output")]
public bool? Verbose { get; internal set; }
public bool? Verbose { get; set; }


public static void Run(string[] args, Func<CommandLineSettings, int> callback)
Expand Down
92 changes: 38 additions & 54 deletions src/Microsoft.Azure.Relay.Bridge/Configuration/Config.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ namespace Microsoft.Azure.Relay.Bridge.Configuration
using System.Runtime.Serialization;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
using YamlDotNet.Core;

/// <summary>
Expand All @@ -26,14 +28,12 @@ public class Config : IDisposable
{
private const string AzureBridgeName = "azbridge";
RelayConnectionStringBuilder relayConnectionStringBuilder;
readonly List<FileSystemWatcher> fileSystemWatchers;
List<LocalForward> localForward;
List<RemoteForward> remoteForward;

public Config()
{
relayConnectionStringBuilder = new RelayConnectionStringBuilder();
fileSystemWatchers = new List<FileSystemWatcher>();
localForward = new List<LocalForward>();
remoteForward = new List<RemoteForward>();
}
Expand Down Expand Up @@ -462,12 +462,6 @@ public List<RemoteForward> RemoteForward
}
}

internal event EventHandler<ConfigChangedEventArgs> Changed;
void RaiseChanged(Config newConfig)
{
Changed?.Invoke(this, new ConfigChangedEventArgs { OldConfig = this, NewConfig = newConfig });
}

public static Config LoadConfig(CommandLineSettings commandLineSettings)
{
const string azbridge = AzureBridgeName;
Expand All @@ -477,16 +471,6 @@ public static Config LoadConfig(CommandLineSettings commandLineSettings)
Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData), $"{azbridge}\\{azbridge}_config.machine.yml");

Config config = LoadConfigFile(machineConfigFileName);
Action onchange = () => { var cfg = LoadConfig(commandLineSettings); config.RaiseChanged(cfg); };

if (Directory.Exists(Path.GetDirectoryName(machineConfigFileName)))
{
var fsw = new FileSystemWatcher(Path.GetDirectoryName(machineConfigFileName), Path.GetFileName(machineConfigFileName));
fsw.Created += (o, e) => onchange();
fsw.Deleted += (o, e) => onchange();
fsw.Changed += (o, e) => onchange();
config.fileSystemWatchers.Add(fsw);
}

if (string.IsNullOrEmpty(commandLineSettings.ConfigFile))
{
Expand All @@ -498,27 +482,11 @@ public static Config LoadConfig(CommandLineSettings commandLineSettings)

Config userConfig = LoadConfigFile(userConfigFileName);
config.Merge(userConfig);
if (Directory.Exists(Path.GetDirectoryName(userConfigFileName)))
{
var fsw = new FileSystemWatcher(Path.GetDirectoryName(userConfigFileName), Path.GetFileName(userConfigFileName));
fsw.Created += (o, e) => onchange();
fsw.Deleted += (o, e) => onchange();
fsw.Changed += (o, e) => onchange();
config.fileSystemWatchers.Add(fsw);
}
}
else
{
Config overrideConfig = LoadConfigFile(commandLineSettings.ConfigFile);
config.Merge(overrideConfig);
if (Directory.Exists(Path.GetDirectoryName(commandLineSettings.ConfigFile)))
{
var fsw = new FileSystemWatcher(Path.GetDirectoryName(commandLineSettings.ConfigFile), Path.GetFileName(commandLineSettings.ConfigFile));
fsw.Created += (o, e) => onchange();
fsw.Deleted += (o, e) => onchange();
fsw.Changed += (o, e) => onchange();
config.fileSystemWatchers.Add(fsw);
}
}

if (commandLineSettings.Option != null)
Expand Down Expand Up @@ -968,7 +936,7 @@ private static void ParseRemoteHttpForward(Config config, string rf, bool newFor
try
{
StringBuilder path = new StringBuilder("/");
for(int i = 2; i < portStrings.Length; i++)
for (int i = 2; i < portStrings.Length; i++)
{
path.Append(portStrings[i]).Append("/");
}
Expand Down Expand Up @@ -996,7 +964,7 @@ private static void ParseRemoteHttpForward(Config config, string rf, bool newFor
string portString;
string portName;


var portStrings = rfs[0].Split('/');
if (portStrings.Length < 2)
{
Expand Down Expand Up @@ -1170,18 +1138,47 @@ public static Config LoadConfigFile(string fileName)

if (File.Exists(fileName))
{

using (var reader = new StreamReader(fileName))
// test whether the file is locked for reading; if so we'll spin wait
// for a bit and then throw an exception
for (int i = 0; i < 10; i++)
{
try
{
return yamlDeserializer.Deserialize<Config>(reader);
using (var fs = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.None))
{
if (fs.CanRead)
{
try
{
using (var reader = new StreamReader(fs))
{
Config cfg = yamlDeserializer.Deserialize<Config>(reader);
if (cfg == null)
{
throw BridgeEventSource.Log.ArgumentOutOfRange(
nameof(fileName),
$"Invalid configuration file: {fileName}",
null);
}
return cfg;
}
}
catch (YamlException e)
{
throw MapYamlException(fileName, e);
}
}
}
}
catch (YamlException e)
catch (IOException)
{
throw MapYamlException(fileName, e);
Thread.Sleep(1000);
}
}
throw BridgeEventSource.Log.ArgumentOutOfRange(
nameof(fileName),
$"Configuration file {fileName} is locked for reading",
null);
}
else
{
Expand Down Expand Up @@ -1252,13 +1249,6 @@ protected virtual void Dispose(bool disposing)
{
if (!disposedValue)
{
if (disposing)
{
foreach (var w in fileSystemWatchers)
{
w.Dispose();
}
}
disposedValue = true;
}
}
Expand All @@ -1269,10 +1259,4 @@ public void Dispose()
}

}

class ConfigChangedEventArgs : EventArgs
{
public Config OldConfig { get; set; }
public Config NewConfig { get; set; }
}
}
29 changes: 21 additions & 8 deletions src/Microsoft.Azure.Relay.Bridge/Host.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,13 @@ namespace Microsoft.Azure.Relay.Bridge
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;

public class Host
public class Host : IDisposable
{
LocalForwardHost hybridConnectionTcpListenerHost;
RemoteForwardHost hybridConnectionTcpClientHost;
private Config config;
EventTraceActivity hostActivity = BridgeEventSource.NewActivity("Host");
private bool disposedValue;

public Host(Config config)
{
Expand Down Expand Up @@ -54,20 +55,13 @@ public static TokenProvider DefaultAzureCredentialTokenProvider
public void Start()
{
hostActivity.DiagnosticsActivity.Start();
this.config.Changed += ConfigChanged;
this.hybridConnectionTcpClientHost = new RemoteForwardHost(config);
this.hybridConnectionTcpListenerHost = new LocalForwardHost(config);

this.hybridConnectionTcpClientHost.Start();
this.hybridConnectionTcpListenerHost.Start();
}

private void ConfigChanged(object sender, ConfigChangedEventArgs e)
{
this.config = e.NewConfig;
hybridConnectionTcpClientHost.UpdateConfig(config);
hybridConnectionTcpListenerHost.UpdateConfig(config);
}

public static void SaveConfig(string configFilePath, Config connectionConfig)
{
Expand Down Expand Up @@ -98,9 +92,28 @@ public static void SaveConfig(string configFilePath, Config connectionConfig)

public void Stop()
{
disposedValue = true;
this.hybridConnectionTcpClientHost.Stop();
this.hybridConnectionTcpListenerHost.Stop();
hostActivity.DiagnosticsActivity.Stop();
}

protected virtual void Dispose(bool disposing)
{
if (!disposedValue)
{
if (disposing)
{
this.Stop();
}
disposedValue = true;
}
}

public void Dispose()
{
Dispose(disposing: true);
GC.SuppressFinalize(this);
}
}
}
6 changes: 6 additions & 0 deletions test/unit/Microsoft.Azure.Relay.Bridge.Tests/ConfigTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@ namespace Microsoft.Azure.Relay.Bridge.Test
using System.Configuration;
using System.Globalization;
using System.IO;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using McMaster.Extensions.CommandLineUtils;
using Microsoft.Azure.Relay.Bridge.Configuration;
Expand Down Expand Up @@ -164,6 +166,9 @@ public void CommandLineTOptionTest()
Assert.True(callbackInvoked);
}




[Fact]
public void CommandLineROptionTest()
{
Expand Down Expand Up @@ -855,5 +860,6 @@ public void ConfigSaveLoadFileTest()
File.Delete(configFileName);
}
}

}
}
Loading