public SyncthingDebugFacilitiesManager(SynchronizedTransientWrapper<ISyncthingApiClient> apiClient, ISyncthingCapabilities capabilities)
        {
            this.apiClient = apiClient;
            this.capabilities = capabilities;

            this.SupportsRestartlessUpdate = false;
            this.DebugFacilities = new List<DebugFacility>();
        }
Example #2
0
        public SyncthingDebugFacilitiesManager(SynchronizedTransientWrapper <ISyncthingApiClient> apiClient, ISyncthingCapabilities capabilities)
        {
            this.apiClient    = apiClient;
            this.capabilities = capabilities;

            this.SupportsRestartlessUpdate = false;
            this.DebugFacilities           = new List <DebugFacility>();
        }
        public SyncthingDeviceManager(SynchronizedTransientWrapper <ISyncthingApiClient> apiClient, ISyncthingEventWatcher eventWatcher, ISyncthingCapabilities capabilities)
        {
            this.eventDispatcher = new SynchronizedEventDispatcher(this);
            this.apiClient       = apiClient ?? throw new ArgumentNullException(nameof(apiClient));
            this.eventWatcher    = eventWatcher ?? throw new ArgumentNullException(nameof(eventWatcher));
            this.capabilities    = capabilities ?? throw new ArgumentNullException(nameof(capabilities));

            this.eventWatcher.DeviceConnected    += this.EventDeviceConnected;
            this.eventWatcher.DeviceDisconnected += this.EventDeviceDisconnected;
            this.eventWatcher.DevicePaused       += this.EventDevicePaused;
            this.eventWatcher.DeviceResumed      += this.EventDeviceResumed;
        }
Example #4
0
        public SyncthingDeviceManager(SynchronizedTransientWrapper <ISyncthingApiClient> apiClient, ISyncthingEventWatcher eventWatcher, ISyncthingCapabilities capabilities)
        {
            this.eventDispatcher = new SynchronizedEventDispatcher(this);
            this.apiClient       = apiClient;
            this.eventWatcher    = eventWatcher;
            this.capabilities    = capabilities;

            this.eventWatcher.DeviceConnected    += this.EventDeviceConnected;
            this.eventWatcher.DeviceDisconnected += this.EventDeviceDisconnected;
            this.eventWatcher.DevicePaused       += this.EventDevicePaused;
            this.eventWatcher.DeviceResumed      += this.EventDeviceResumed;
        }
        public SyncthingDeviceManager(SynchronizedTransientWrapper<ISyncthingApiClient> apiClient, ISyncthingEventWatcher eventWatcher, ISyncthingCapabilities capabilities)
        {
            this.eventDispatcher = new SynchronizedEventDispatcher(this);
            this.apiClient = apiClient;
            this.eventWatcher = eventWatcher;
            this.capabilities = capabilities;

            this.eventWatcher.DeviceConnected += this.EventDeviceConnected;
            this.eventWatcher.DeviceDisconnected += this.EventDeviceDisconnected;
            this.eventWatcher.DevicePaused += this.EventDevicePaused;
            this.eventWatcher.DeviceResumed += this.EventDeviceResumed;
        }
        public SyncThingFolderManager(
            SynchronizedTransientWrapper<ISyncThingApiClient> apiClient,
            ISyncThingEventWatcher eventWatcher,
            TimeSpan ignoresFetchTimeout)
        {
            this.eventDispatcher = new SynchronizedEventDispatcher(this);
            this.apiClient = apiClient;
            this.ignoresFetchTimeout = ignoresFetchTimeout;

            this.eventWatcher = eventWatcher;
            this.eventWatcher.SyncStateChanged += (o, e) => this.FolderSyncStateChanged(e);
            this.eventWatcher.ItemStarted += (o, e) => this.ItemStarted(e.Folder, e.Item);
            this.eventWatcher.ItemFinished += (o, e) => this.ItemFinished(e.Folder, e.Item);
        }
Example #7
0
        public SyncthingFolderManager(
            SynchronizedTransientWrapper <ISyncthingApiClient> apiClient,
            ISyncthingEventWatcher eventWatcher)
        {
            this.eventDispatcher = new SynchronizedEventDispatcher(this);
            this.apiClient       = apiClient;

            this.eventWatcher = eventWatcher;
            this.eventWatcher.SyncStateChanged    += (o, e) => this.FolderSyncStateChanged(e);
            this.eventWatcher.FolderStatusChanged += (o, e) => this.FolderStatusChanged(e.FolderId, e.FolderStatus);
            this.eventWatcher.ItemStarted         += (o, e) => this.ItemStarted(e.Folder, e.Item);
            this.eventWatcher.ItemFinished        += (o, e) => this.ItemFinished(e.Folder, e.Item);
            this.eventWatcher.FolderErrorsChanged += (o, e) => this.FolderErrorsChangedEvt(e.FolderId, e.Errors);
        }
 public ISyncThingEventWatcher CreateEventWatcher(SynchronizedTransientWrapper<ISyncThingApiClient> apiClient)
 {
     return new SyncThingEventWatcher(apiClient);
 }
Example #9
0
        public SyncthingManager(
            ISyncthingProcessRunner processRunner,
            ISyncthingApiClientFactory apiClientFactory,
            ISyncthingEventWatcherFactory eventWatcherFactory,
            ISyncthingConnectionsWatcherFactory connectionsWatcherFactory,
            IFreePortFinder freePortFinder)
        {
            this.StartedTime = DateTime.MinValue;
            this.LastConnectivityEventTime = DateTime.MinValue;

            this.eventDispatcher = new SynchronizedEventDispatcher(this);
            this.processRunner = processRunner;
            this.apiClientFactory = apiClientFactory;
            this.freePortFinder = freePortFinder;

            this.apiClient = new SynchronizedTransientWrapper<ISyncthingApiClient>(this.apiClientsLock);

            this.eventWatcher = eventWatcherFactory.CreateEventWatcher(this.apiClient);
            this.eventWatcher.DeviceConnected += (o, e) => this.LastConnectivityEventTime = DateTime.UtcNow;
            this.eventWatcher.DeviceDisconnected += (o, e) => this.LastConnectivityEventTime = DateTime.UtcNow;
            this.eventWatcher.ConfigSaved += (o, e) => this.ReloadConfigDataAsync();
            this.eventWatcher.EventsSkipped += (o, e) => this.ReloadConfigDataAsync();

            this.connectionsWatcher = connectionsWatcherFactory.CreateConnectionsWatcher(this.apiClient);
            this.connectionsWatcher.TotalConnectionStatsChanged += (o, e) => this.OnTotalConnectionStatsChanged(e.TotalConnectionStats);

            this._folders = new SyncthingFolderManager(this.apiClient, this.eventWatcher, TimeSpan.FromMinutes(10));
            this._devices = new SyncthingDeviceManager(this.apiClient, this.eventWatcher, this.Capabilities);
            this._transferHistory = new SyncthingTransferHistory(this.eventWatcher, this._folders);
            this._debugFacilities = new SyncthingDebugFacilitiesManager(this.apiClient, this.Capabilities);

            this.processRunner.ProcessStopped += (o, e) => this.ProcessStopped(e.ExitStatus);
            this.processRunner.MessageLogged += (o, e) => this.OnMessageLogged(e.LogMessage);
            this.processRunner.ProcessRestarted += (o, e) => this.ProcessRestarted();
            this.processRunner.Starting += (o, e) => this.ProcessStarting();
        }
 public ISyncThingConnectionsWatcher CreateConnectionsWatcher(SynchronizedTransientWrapper<ISyncThingApiClient> apiClient)
 {
     return new SyncThingConnectionsWatcher(apiClient);
 }
        private async Task<Ignores> FetchFolderIgnoresAsync(string folderId, CancellationToken cancellationToken)
        {
            // Until startup is complete, these can return a 500.
            // There's no sensible way to determine when startup *is* complete, so we just have to keep trying...

            // Again, there's the possibility that we've just abort the API...
            ISyncThingApiClient apiClient;
            lock (this.apiClient.LockObject)
            {
                cancellationToken.ThrowIfCancellationRequested();
                apiClient = this.apiClient.UnsynchronizedValue;
                if (apiClient == null)
                    throw new InvalidOperationException("ApiClient must not be null");
            }

            Ignores ignores = null;
            // We used to time out after an absolute time here. However, there's the possiblity of going to sleep
            // halfway through polling, which throws things off. Therefore use a number of iterations
            var numRetries = this.ignoresFetchTimeout.TotalSeconds; // Each iteration is a second
            for (var retriesCount = 0; retriesCount < numRetries; retriesCount++)
            {
                try
                {
                    ignores = await apiClient.FetchIgnoresAsync(folderId);
                    // No need to log: ApiClient did that for us
                    break;
                }
                catch (ApiException e)
                {
                    logger.Debug("Attempting to fetch folder {0}, but received status {1}", folderId, e.StatusCode);
                    if (e.StatusCode != HttpStatusCode.InternalServerError)
                        throw;
                }

                await Task.Delay(1000, cancellationToken);
                cancellationToken.ThrowIfCancellationRequested();
            }

            if (ignores == null)
                throw new SyncThingDidNotStartCorrectlyException($"Unable to fetch ignores for folder {folderId}. Syncthing returned 500 after {this.ignoresFetchTimeout}");

            return ignores;
        }
 public SyncThingConnectionsWatcher(SynchronizedTransientWrapper<ISyncThingApiClient> apiClient)
     : base(TimeSpan.FromSeconds(5), TimeSpan.FromSeconds(10))
 {
     this.apiClientWrapper = apiClient;
 }
 public ISyncthingEventWatcher CreateEventWatcher(SynchronizedTransientWrapper <ISyncthingApiClient> apiClient)
 {
     return(new SyncthingEventWatcher(apiClient));
 }
 public SyncThingEventWatcher(SynchronizedTransientWrapper<ISyncThingApiClient> apiClient)
     : base(TimeSpan.Zero, TimeSpan.FromSeconds(10))
 {
     this.apiClientWrapper = apiClient;
 }
Example #15
0
 public SyncthingEventWatcher(SynchronizedTransientWrapper <ISyncthingApiClient> apiClient)
     : base(TimeSpan.Zero, TimeSpan.FromSeconds(10))
 {
     this.apiClientWrapper = apiClient;
 }
        private async Task LoadStartupDataAsync(CancellationToken cancellationToken)
        {
            logger.Debug("Startup Complete! Loading startup data");

            // There's a race where Syncthing died, and so we kill the API clients and set it to null,
            // but we still end up here, because threading.
            ISyncThingApiClient apiClient;
            lock (this.apiClientsLock)
            {
                cancellationToken.ThrowIfCancellationRequested();
                apiClient = this.apiClient.UnsynchronizedValue;
                if (apiClient == null)
                    throw new InvalidOperationException("ApiClient must not be null");
            }

            var configTask = apiClient.FetchConfigAsync();
            var systemTask = apiClient.FetchSystemInfoAsync();
            var versionTask = apiClient.FetchVersionAsync();
            var connectionsTask = apiClient.FetchConnectionsAsync();

            cancellationToken.ThrowIfCancellationRequested();
            await Task.WhenAll(configTask, systemTask, versionTask, connectionsTask);

            // We can potentially see duplicate devices (if the user set their config file that way). Ignore them.
            var devices = configTask.Result.Devices.DistinctBy(x => x.DeviceID).Select(device =>
            {
                var deviceObj = new Device(device.DeviceID, device.Name);
                ItemConnectionData connectionData;
                if (connectionsTask.Result.DeviceConnections.TryGetValue(device.DeviceID, out connectionData))
                    deviceObj.SetConnected(connectionData.Address);
                return deviceObj;
            });
            this.devices = new ConcurrentDictionary<string, Device>(devices.Select(x => new KeyValuePair<string, Device>(x.DeviceId, x)));

            await this._folders.LoadFoldersAsync(configTask.Result, systemTask.Result, cancellationToken);

            this.Version = versionTask.Result;

            cancellationToken.ThrowIfCancellationRequested();
            
            this.StartedTime = DateTime.UtcNow;
            this.IsDataLoaded = true;
            this.OnDataLoaded();
        }