/// <summary> /// Sets the new config safely, waiting until syncs have completed. /// </summary> private void SetNewConfig(Config newConfig) { _logger.LogDebug( "new config received"); if (_syncing) { //Wait until sync completes before setting new Config lock (_configChangedLock) { Monitor.Wait(_configChangedLock); } } //Migrate in memory sync times to the new config so we don't lose them foreach (var path in newConfig.Paths) { var match = _config.Paths.Find(f => f.Path == path.Path); if (match is not null) { path.LastSynced = match.LastSynced; } } //Swap and save new config _config = newConfig; FileSyncUtility.SaveConfig(_config, _confLocation); //Begin a new sync regardless of wait time lock (_waitIntervalLock) { Monitor.Pulse(_waitIntervalLock); } }
public MainWindow() { InitializeComponent(); _client = new PipeClient("syncsharp"); Closed += (sender, args) => Disconnect(sender, null); _vm = new SyncViewModel(); //Load conf from correct directory #if DEBUG _vm.Config = FileSyncUtility.LoadConfig(@"..\..\..\..\SyncSharpWorker\bin\Debug\net5.0\conf.bin"); #else _vm.Config = FileSyncUtility.LoadConfig(@$ "..{Path.DirectorySeparatorChar}SyncSharpWorker\conf.bin"); #endif PathListView.ItemsSource = _vm.Config.Paths; BackupIntervalInput.Text = _vm.Config.CheckInterval.ToString(); }
protected override async Task ExecuteAsync(CancellationToken stoppingToken) { //Wake main thread if cancelled stoppingToken.Register(() => { lock (_waitIntervalLock) { Monitor.Pulse(_waitIntervalLock); } }); //Start server thread _ = Task.Run((async() => { //Continuously listen for new configs from the GUI outer: while (!stoppingToken.IsCancellationRequested) { _logger.LogDebug("Waiting on connection..."); await _pipeServer.WaitForConnectionAsync(stoppingToken); const int bufferSize = 4000; Memory <byte> buffer = new byte[bufferSize]; //Use list as a dynamic 'buffer' var accList = new List <byte>(); _logger.LogDebug("Pipe Connected"); while (!stoppingToken.IsCancellationRequested) { //Reset Transfer size var lastByteTransferSize = 0; //Keep reading from stream until empty do { var task = _pipeServer.ReadAsync(buffer, stoppingToken); await task; _logger.LogDebug($"Finished reading {task.Result} bytes from pipe"); lastByteTransferSize = task.Result; //Move buffer to list and clear buffer accList.AddRange(buffer.ToArray()); buffer.Span.Clear(); } while (lastByteTransferSize == bufferSize); var bytesRead = accList.ToArray().AsSpan().TrimEnd((byte)0).Length; _logger.LogDebug($"finished reading a total of {bytesRead} bytes from pipe."); //A one byte message means we should disconnect if (bytesRead == 1) { _logger.LogDebug("Disconnect bit received, disconnecting"); _pipeServer.Disconnect(); goto outer; } //Trim excess 0s from the end of buffer> WILL NOT serialize without this var newConfig = Serializer.Deserialize <Config>(accList.ToArray().AsSpan().TrimEnd((byte)0)); //Safely apply the new config SetNewConfig(newConfig); //Reset buffers buffer.Span.Clear(); accList.Clear(); } } }), stoppingToken); while (!stoppingToken.IsCancellationRequested) { //Wait time between syncs lock (_waitIntervalLock) { _logger.LogDebug($"entering sleep for {_config.CheckInterval}"); Monitor.Wait(_waitIntervalLock, _config.CheckInterval); } _syncing = true; _logger.LogDebug($"woke, starting sync"); await FileSyncUtility.Sync(_config, stoppingToken, _logger); _syncing = false; //Signal that syncs are done lock (_configChangedLock) { Monitor.Pulse(_configChangedLock); } } }
private Config GetConfig() { return(FileSyncUtility.LoadConfig(_confLocation)); }