Example #1
0
        /// <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();
        }
Example #3
0
        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);
                }
            }
        }
Example #4
0
 private Config GetConfig()
 {
     return(FileSyncUtility.LoadConfig(_confLocation));
 }