private void SetState(SyncThingState state) { SyncThingState oldState; bool abortApi = false; lock (this.stateLock) { logger.Debug("Request to set state: {0} -> {1}", this._state, state); if (state == this._state) { return; } oldState = this._state; // We really need a proper state machine here.... // There's a race if Syncthing can't start because the database is locked by another process on the same port // In this case, we see the process as having failed, but the event watcher chimes in a split-second later with the 'Started' event. // This runs the risk of transitioning us from Stopped -> Starting -> Stopped -> Running, which is bad news for everyone // So, get around this by enforcing strict state transitions. if (this._state == SyncThingState.Stopped && state == SyncThingState.Running) { return; } // Not entirely sure where this condition comes from... if (this._state == SyncThingState.Stopped && state == SyncThingState.Stopping) { return; } if (this._state == SyncThingState.Running || (this._state == SyncThingState.Starting && state == SyncThingState.Stopped)) { abortApi = true; } logger.Debug("Setting state: {0} -> {1}", this._state, state); this._state = state; } if (abortApi) { logger.Debug("Aborting API clients"); // StopApiClients acquires the correct locks, and aborts the CTS this.StopApiClients(); } this.eventDispatcher.Raise(this.StateChanged, new SyncThingStateChangedEventArgs(oldState, state)); }
public ShellViewModel( IWindowManager windowManager, ISyncThingManager syncThingManager, IApplicationState application, IConfigurationProvider configurationProvider, ConsoleViewModel console, ViewerViewModel viewer, Func <SettingsViewModel> settingsViewModelFactory, Func <AboutViewModel> aboutViewModelFactory, IProcessStartProvider processStartProvider) { this.windowManager = windowManager; this.syncThingManager = syncThingManager; this.application = application; this.configurationProvider = configurationProvider; this.Console = console; this.Viewer = viewer; this.settingsViewModelFactory = settingsViewModelFactory; this.aboutViewModelFactory = aboutViewModelFactory; this.processStartProvider = processStartProvider; var configuration = this.configurationProvider.Load(); this.Console.ConductWith(this); this.Viewer.ConductWith(this); this.syncThingManager.StateChanged += (o, e) => this.SyncThingState = e.NewState; this.syncThingManager.ProcessExitedWithError += (o, e) => this.ShowExitedWithError(); this.ConsoleHeight = configuration.SyncthingConsoleHeight; this.Bind(s => s.ConsoleHeight, (o, e) => this.configurationProvider.AtomicLoadAndSave(c => c.SyncthingConsoleHeight = e.NewValue)); this.ShowConsole = configuration.SyncthingConsoleHeight > 0; this.Bind(s => s.ShowConsole, (o, e) => { this.ConsoleHeight = e.NewValue ? Configuration.DefaultSyncthingConsoleHeight : 0.0; }); this.Placement = configuration.WindowPlacement; this.Bind(s => s.Placement, (o, e) => this.configurationProvider.AtomicLoadAndSave(c => c.WindowPlacement = e.NewValue)); }
public ShellViewModel( IWindowManager windowManager, ISyncThingManager syncThingManager, IApplicationState application, IConfigurationProvider configurationProvider, ConsoleViewModel console, ViewerViewModel viewer, Func<SettingsViewModel> settingsViewModelFactory, Func<AboutViewModel> aboutViewModelFactory, IProcessStartProvider processStartProvider) { this.windowManager = windowManager; this.syncThingManager = syncThingManager; this.application = application; this.configurationProvider = configurationProvider; this.Console = console; this.Viewer = viewer; this.settingsViewModelFactory = settingsViewModelFactory; this.aboutViewModelFactory = aboutViewModelFactory; this.processStartProvider = processStartProvider; var configuration = this.configurationProvider.Load(); this.Console.ConductWith(this); this.Viewer.ConductWith(this); this.syncThingManager.StateChanged += (o, e) => this.SyncThingState = e.NewState; this.syncThingManager.ProcessExitedWithError += (o, e) => this.ShowExitedWithError(); this.ConsoleHeight = configuration.SyncthingConsoleHeight; this.Bind(s => s.ConsoleHeight, (o, e) => this.configurationProvider.AtomicLoadAndSave(c => c.SyncthingConsoleHeight = e.NewValue)); this.ShowConsole = configuration.SyncthingConsoleHeight > 0; this.Bind(s => s.ShowConsole, (o, e) => { this.ConsoleHeight = e.NewValue ? Configuration.DefaultSyncthingConsoleHeight : 0.0; }); this.Placement = configuration.WindowPlacement; this.Bind(s => s.Placement, (o, e) => this.configurationProvider.AtomicLoadAndSave(c => c.WindowPlacement = e.NewValue)); }
private void SetState(SyncThingState state) { SyncThingState oldState; bool abortApi = false; lock (this.stateLock) { logger.Debug("Request to set state: {0} -> {1}", this._state, state); if (state == this._state) return; oldState = this._state; // We really need a proper state machine here.... // There's a race if Syncthing can't start because the database is locked by another process on the same port // In this case, we see the process as having failed, but the event watcher chimes in a split-second later with the 'Started' event. // This runs the risk of transitioning us from Stopped -> Starting -> Stopped -> Running, which is bad news for everyone // So, get around this by enforcing strict state transitions. if (this._state == SyncThingState.Stopped && state == SyncThingState.Running) return; // Not entirely sure where this condition comes from... if (this._state == SyncThingState.Stopped && state == SyncThingState.Stopping) return; if (this._state == SyncThingState.Running || (this._state == SyncThingState.Starting && state == SyncThingState.Stopped)) abortApi = true; logger.Debug("Setting state: {0} -> {1}", this._state, state); this._state = state; } if (abortApi) { logger.Debug("Aborting API clients"); // StopApiClients acquires the correct locks, and aborts the CTS this.StopApiClients(); } this.eventDispatcher.Raise(this.StateChanged, new SyncThingStateChangedEventArgs(oldState, state)); }
public SyncThingStateChangedEventArgs(SyncThingState oldState, SyncThingState newState) { this.OldState = oldState; this.NewState = newState; }