Exemplo n.º 1
0
        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...
            // It's slightly evil to re-use SyncthingConnectTimeout here, but...

            // Again, there's the possibility that we've just abort the API...
            ISyncThingApiClient apiClient;

            lock (this.apiClientsLock)
            {
                cancellationToken.ThrowIfCancellationRequested();
                apiClient = this.apiClient;
                if (apiClient == null)
                {
                    throw new InvalidOperationException("ApiClient must not be null");
                }
            }

            Ignores ignores;
            var     startedTime = DateTime.UtcNow;

            while (true)
            {
                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;
                    }
                }

                if (DateTime.UtcNow - startedTime > this.SyncthingConnectTimeout)
                {
                    throw new SyncThingDidNotStartCorrectlyException(String.Format("Unable to fetch ignores for folder {0}. Syncthing returned 500 after {1}", folderId, DateTime.UtcNow - startedTime));
                }

                await Task.Delay(1000, cancellationToken);

                cancellationToken.ThrowIfCancellationRequested();
            }

            return(ignores);
        }
Exemplo n.º 2
0
        private async Task CreateApiClientAsync(CancellationToken cancellationToken)
        {
            logger.Debug("Starting API clients");
            var apiClient = await this.apiClientFactory.CreateCorrectApiClientAsync(this.Address, this.ApiKey, this.SyncthingConnectTimeout, cancellationToken);

            logger.Debug("Have the API client! It's {0}", apiClient.GetType().Name);

            lock (this.apiClientsLock)
            {
                this.apiClient = apiClient;
            }

            this.SetState(SyncThingState.Running);
        }
Exemplo n.º 3
0
        private void StopApiClients()
        {
            lock (this.apiClientsLock)
            {
                if (this.apiAbortCts != null)
                {
                    this.apiAbortCts.Cancel();
                }

                this.apiClient = null;

                if (this.connectionsWatcher != null)
                {
                    this.connectionsWatcher.Dispose();
                }
                this.connectionsWatcher = null;

                if (this.eventWatcher != null)
                {
                    this.eventWatcher.Dispose();
                }
                this.eventWatcher = null;
            }
        }
 protected override void OnStop()
 {
     this.apiClient = null;
 }
 protected override void OnStart()
 {
     this.apiClient = this.apiClientWrapper.Value;
 }
Exemplo n.º 6
0
        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;
                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)));

            var tilde = systemTask.Result.Tilde;

            // If the folder is invalid for any reason, we'll ignore it.
            // Again, there's the potential for duplicate folder IDs (if the user's been fiddling their config).
            // In this case, there's nothing really sensible we can do. Just pick one of them :)
            var folderConstructionTasks = configTask.Result.Folders
                                          .Where(x => String.IsNullOrWhiteSpace(x.Invalid))
                                          .DistinctBy(x => x.ID)
                                          .Select(async folder =>
            {
                var ignores = await this.FetchFolderIgnoresAsync(folder.ID, cancellationToken);
                var path    = folder.Path;
                if (path.StartsWith("~"))
                {
                    path = Path.Combine(tilde, path.Substring(1).TrimStart(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar));
                }
                return(new Folder(folder.ID, path, new FolderIgnores(ignores.IgnorePatterns, ignores.RegexPatterns)));
            });

            cancellationToken.ThrowIfCancellationRequested();

            var folders = await Task.WhenAll(folderConstructionTasks);

            this.folders = new ConcurrentDictionary <string, Folder>(folders.Select(x => new KeyValuePair <string, Folder>(x.FolderId, x)));

            this.Version = versionTask.Result;

            cancellationToken.ThrowIfCancellationRequested();

            this.StartedTime  = DateTime.UtcNow;
            this.IsDataLoaded = true;
            this.OnDataLoaded();
        }
 public ISyncThingEventWatcher CreateEventWatcher(ISyncThingApiClient apiClient)
 {
     return(new SyncThingEventWatcher(apiClient));
 }
Exemplo n.º 8
0
 public SyncThingEventWatcher(ISyncThingApiClient apiClient)
     : base(TimeSpan.Zero, TimeSpan.FromSeconds(10))
 {
     this.apiClient = apiClient;
 }
Exemplo n.º 9
0
 public ISyncThingConnectionsWatcher CreateConnectionsWatcher(ISyncThingApiClient apiClient)
 {
     return(new SyncThingConnectionsWatcher(apiClient));
 }
 public SyncThingConnectionsWatcher(ISyncThingApiClient apiClient)
     : base(TimeSpan.FromSeconds(5), TimeSpan.FromSeconds(10))
 {
     this.apiClient = apiClient;
 }
Exemplo n.º 11
0
 protected override void OnStop()
 {
     this.apiClient = null;
 }
Exemplo n.º 12
0
 protected override void OnStart()
 {
     this.apiClient = this.apiClientWrapper.Value;
 }