Esempio n. 1
0
 /// <inheritdoc />
 public void Init(ProfilerThread Thread)
 {
     if (this.currentState == StorageState.NotInitialized)
     {
         this.currentState   = StorageState.Initializing;
         this.initializeTask = InitializeAsync(Thread);
     }
 }
Esempio n. 2
0
        private async Task Subtask(ProfilerThread Thread)
        {
            await Task.Delay(rnd.Next(10, 1000));

            Thread.Start();
            Thread.NewState("A");
            await Task.Delay(rnd.Next(10, 1000));

            Thread.NewState("B");
            await Task.Delay(rnd.Next(10, 1000));

            Thread.NewState("C");
            await Task.Delay(rnd.Next(10, 1000));

            Thread.NewState("D");
            await Task.Delay(rnd.Next(10, 1000));

            Thread.Stop();
        }
Esempio n. 3
0
        /// <inheritdoc />
        public async Task TryRepairDatabase(ProfilerThread Thread)
        {
            if (await this.uiDispatcher.DisplayAlert(AppResources.DatabaseIssue, AppResources.DatabaseCorruptInfoText, AppResources.RepairAndContinue, AppResources.ContinueAnyway))
            {
                string method = "Delete database file(s) and create new empty database";
                try
                {
                    Thread?.NewState("Delete");

                    // 3. Delete and create a new empty database
                    Directory.Delete(dataFolder, true);

                    Thread?.NewState("Recreate");

                    this.databaseProvider = await CreateDatabaseFile();

                    Thread?.NewState("Repair3");

                    await this.databaseProvider.RepairIfInproperShutdown(string.Empty);

                    // If we had to repair, we must register the provider 'again', as one hasn't been provided yet.
                    if (!Database.HasProvider)
                    {
                        method = $"{nameof(Database)}.{nameof(Database.Register)}";
                        Database.Register(databaseProvider, false);
                    }
                    // All is good.
                    this.SetState(StorageState.Ready);
                }
                catch (Exception e3)
                {
                    e3 = Log.UnnestException(e3);
                    Thread?.Exception(e3);

                    // Delete and create new failed. We're out of options.
                    this.logService.LogException(e3, this.GetClassAndMethod(MethodBase.GetCurrentMethod(), method));

                    Thread?.NewState("DisplayAlert2");

                    await this.uiDispatcher.DisplayAlert(AppResources.DatabaseIssue, AppResources.DatabaseRepairFailedInfoText, AppResources.Ok);
                }
            }
        }
Esempio n. 4
0
 /// <summary>
 /// Thread goes idle.
 /// </summary>
 /// <param name="Ticks">Elapsed ticks.</param>
 /// <param name="Thread">Profiler thread generating the event.</param>
 public Idle(long Ticks, ProfilerThread Thread)
     : base(Ticks, Thread)
 {
 }
Esempio n. 5
0
 /// <summary>
 /// Abstract base class for profiler events.
 /// </summary>
 /// <param name="Ticks">Elapsed ticks.</param>
 /// <param name="Thread">Profiler thread generating the event.</param>
 public ProfilerEvent(long Ticks, ProfilerThread Thread)
 {
     this.ticks  = Ticks;
     this.thread = Thread;
 }
Esempio n. 6
0
 /// <summary>
 /// Event occurred
 /// </summary>
 /// <param name="Ticks">Elapsed ticks.</param>
 /// <param name="Name">Name of event.</param>
 /// <param name="Thread">Profiler thread generating the event.</param>
 public Event(long Ticks, string Name, ProfilerThread Thread)
     : base(Ticks, Thread)
 {
     this.name = Name;
 }
Esempio n. 7
0
 /// <summary>
 /// Thread changes state.
 /// </summary>
 /// <param name="Ticks">Elapsed ticks.</param>
 /// <param name="State">String representation of the new state.</param>
 /// <param name="Thread">Profiler thread generating the event.</param>
 public NewState(long Ticks, string State, ProfilerThread Thread)
     : base(Ticks, Thread)
 {
     this.state = State;
 }
Esempio n. 8
0
 /// <summary>
 /// Processing stops.
 /// </summary>
 /// <param name="Ticks">Elapsed ticks.</param>
 /// <param name="Thread">Profiler thread generating the event.</param>
 public Stop(long Ticks, ProfilerThread Thread)
     : base(Ticks, Thread)
 {
 }
Esempio n. 9
0
        private async Task CreateXmppClient(bool CanCreateKeys)
        {
            this.xmppThread = this.startupProfiler?.CreateThread("XMPP", ProfilerThreadType.StateMachine);
            this.xmppThread?.Start();
            this.xmppThread?.Idle();

            if (isCreatingClient)
            {
                return;
            }

            try
            {
                isCreatingClient = true;

                if (!(this.xmppClient is null))
                {
                    DestroyXmppClient();
                }
                if (this.xmppClient is null ||
                    this.domainName != this.tagProfile.Domain ||
                    this.accountName != this.tagProfile.Account ||
                    this.passwordHash != this.tagProfile.PasswordHash ||
                    this.passwordHashMethod != this.tagProfile.PasswordHashMethod)
                {
                    this.domainName         = this.tagProfile.Domain;
                    this.accountName        = this.tagProfile.Account;
                    this.passwordHash       = this.tagProfile.PasswordHash;
                    this.passwordHashMethod = this.tagProfile.PasswordHashMethod;

                    (string hostName, int portNumber, bool isIpAddress) = await this.networkService.LookupXmppHostnameAndPort(domainName);

                    this.xmppClient = new XmppClient(hostName, portNumber, accountName, passwordHash, passwordHashMethod, Constants.LanguageCodes.Default, appAssembly, this.sniffer)
                    {
                        TrustServer      = !isIpAddress,
                        AllowCramMD5     = false,
                        AllowDigestMD5   = false,
                        AllowPlain       = false,
                        AllowEncryption  = true,
                        AllowScramSHA1   = true,
                        AllowScramSHA256 = true
                    };

                    this.xmppClient.RequestRosterOnStartup = false;
                    this.xmppClient.OnStateChanged        += XmppClient_StateChanged;
                    this.xmppClient.OnConnectionError     += XmppClient_ConnectionError;
                    this.xmppClient.OnError += XmppClient_Error;
                    this.xmppEventSink       = new XmppEventSink("XMPP Event Sink", this.xmppClient, this.tagProfile.LogJid, false);

                    if (!string.IsNullOrWhiteSpace(this.tagProfile.LegalJid))
                    {
                        await this.contracts.CreateClients(CanCreateKeys);
                    }

                    this.IsLoggedOut = false;
                    this.xmppClient.Connect(isIpAddress ? string.Empty : domainName);

                    bool connectSucceeded = false;
                    // Await connected state during registration or user initiated log in, but not otherwise.
                    if (!this.tagProfile.IsCompleteOrWaitingForValidation() || this.userInitiatedLogInOrOut)
                    {
                        connectSucceeded = await this.WaitForConnectedState(Constants.Timeouts.XmppConnect);
                    }
                    // This saves startup time for registered users with a complete profile
                    if (this.tagProfile.IsComplete())
                    {
                        connectSucceeded = true;
                    }

                    if (!connectSucceeded)
                    {
                        this.logService.LogWarning("Connect to XMPP server '{0}' failed for account '{1}' with the specified timeout of {2} ms",
                                                   this.domainName,
                                                   this.accountName,
                                                   (int)Constants.Timeouts.XmppConnect.TotalMilliseconds);
                    }

                    this.RecreateReconnectTimer();
                }
            }
            finally
            {
                isCreatingClient = false;
            }
        }
Esempio n. 10
0
        private async Task XmppClient_StateChanged(object sender, XmppState newState)
        {
            this.xmppThread?.NewState(newState.ToString());

            switch (newState)
            {
            case XmppState.Connected:
                this.LatestError           = string.Empty;
                this.LatestConnectionError = string.Empty;

                this.xmppSettingsOk = true;

                this.RecreateReconnectTimer();

                string legalJidBefore = this.tagProfile.LegalJid;
                if (this.tagProfile.NeedsUpdating())
                {
                    await this.DiscoverServices();
                }
                string legalJidAfter = this.tagProfile.LegalJid;

                bool legalJidWasCleared           = !string.IsNullOrWhiteSpace(legalJidBefore) && string.IsNullOrWhiteSpace(legalJidAfter);
                bool legalJidIsValid              = !string.IsNullOrWhiteSpace(legalJidAfter);
                bool legalJidHasChangedAndIsValid = legalJidIsValid && !string.Equals(legalJidBefore, legalJidAfter);

                // If LegalJid was cleared, or is different
                if (legalJidWasCleared || legalJidHasChangedAndIsValid)
                {
                    this.contracts.DestroyClients();
                }

                // If we have a valid Jid, and contracts isn't created yet.
                if (legalJidHasChangedAndIsValid || (legalJidIsValid && !this.contracts.IsOnline))
                {
                    try
                    {
                        await this.contracts.CreateClients(false);
                    }
                    catch (Exception e)
                    {
                        this.logService.LogException(e);
                    }
                }

                this.logService.AddListener(this.xmppEventSink);

                this.xmppThread?.Stop();
                this.xmppThread      = null;
                this.startupProfiler = null;
                break;

            case XmppState.Error:
                if (this.xmppSettingsOk)
                {
                    this.xmppSettingsOk = false;
                    this.xmppClient?.Reconnect();
                }

                this.xmppThread?.Stop();
                this.xmppThread      = null;
                this.startupProfiler = null;
                break;
            }

            this.OnConnectionStateChanged(new ConnectionStateChangedEventArgs(newState, this.userInitiatedLogInOrOut));
        }
Esempio n. 11
0
        private async Task PerformStartup(bool isResuming)
        {
            ProfilerThread thread = this.startupProfiler?.MainThread.CreateSubThread("AppStartup", ProfilerThreadType.Sequential);

            thread?.Start();

            try
            {
                thread?.NewState("Report");
                await this.SendErrorReportFromPreviousRun();

                thread?.NewState("Startup");
                ProfilerThread sdkStartupThread = this.startupProfiler?.CreateThread("SdkStartup", ProfilerThreadType.Sequential);
                sdkStartupThread?.Start();
                sdkStartupThread?.NewState("DB");

                this.sdk.UiDispatcher.IsRunningInTheBackground = false;

                // Start the db.
                // This is for soft restarts.
                // If this is a cold start, this call is made already in the App ctor, and this is then a no-op.
                this.sdk.StorageService.Init(sdkStartupThread);
                StorageState dbState = await this.sdk.StorageService.WaitForReadyState();

                if (dbState == StorageState.NeedsRepair)
                {
                    await this.sdk.StorageService.TryRepairDatabase(sdkStartupThread);
                }

                if (!isResuming)
                {
                    await this.CreateOrRestoreConfiguration();
                }

                sdkStartupThread?.NewState("Network");
                await this.sdk.NetworkService.Load(isResuming);

                sdkStartupThread?.NewState("Load");
                await this.sdk.NeuronService.Load(isResuming);

                sdkStartupThread?.NewState("Timer");
                TimeSpan initialAutoSaveDelay = Constants.Intervals.AutoSave.Multiply(4);
                this.autoSaveTimer = new Timer(async _ => await AutoSave(), null, initialAutoSaveDelay, Constants.Intervals.AutoSave);

                sdkStartupThread?.Stop();

                thread?.NewState("Navigation");
                await this.sdk.NavigationService.Load(isResuming);

                thread?.NewState("Cache");
                await this.imageCacheService.Load(isResuming);

                thread?.NewState("Orchestrators");
                await this.contractOrchestratorService.Load(isResuming);

                await this.thingRegistryOrchestratorService.Load(isResuming);
            }
            catch (Exception e)
            {
                e = Waher.Events.Log.UnnestException(e);
                thread?.Exception(e);
                this.DisplayBootstrapErrorPage(e.Message, e.StackTrace);
            }

            thread?.Stop();
            this.StartupCompleted("StartupProfile.uml", false);
        }
Esempio n. 12
0
        private async Task InitializeAsync(ProfilerThread Thread)
        {
            string createDbMethod = $"{nameof(FilesProvider)}.{nameof(FilesProvider.CreateAsync)}()";
            string method         = null;

            Thread?.Start();
            try
            {
                Thread?.NewState("Provider");

                // 1. Try create database
                method = createDbMethod;
                this.databaseProvider = await CreateDatabaseFile();

                Thread?.NewState("Repair");

                method = nameof(FilesProvider.RepairIfInproperShutdown);
                await this.databaseProvider.RepairIfInproperShutdown(string.Empty);
            }
            catch (Exception e1)
            {
                e1 = Log.UnnestException(e1);
                Thread?.Exception(e1);

                // Create failed.
                this.logService.LogException(e1, this.GetClassAndMethod(MethodBase.GetCurrentMethod(), method));

                try
                {
                    Thread?.NewState("Repair2");

                    // 2. Try repair database
                    if (this.databaseProvider is null && Database.HasProvider)
                    {
                        // This is an attempt that _can_ work.
                        // During a soft restart, there _may_ be a provider registered already. If so, grab it.
                        this.databaseProvider = Database.Provider as FilesProvider;
                    }

                    if (this.databaseProvider is null)
                    {
                        // Reasoning: If we can't create a provider, and the database doesn't have one assigned either, we're in serious trouble.
                        // Throw an exception, which is caught below, to try and perform a recovery.
                        const string message = "Database does not have a provider, and one cannot be created because the Database file(s) are locked. Catch 22.";
                        method = createDbMethod;
                        throw new InvalidOperationException(message);
                    }
                    method = nameof(FilesProvider.RepairIfInproperShutdown);
                    await this.databaseProvider.RepairIfInproperShutdown(string.Empty);
                }
                catch (Exception e2)
                {
                    e2 = Log.UnnestException(e2);
                    Thread?.Exception(e2);

                    // Repair failed
                    this.logService.LogException(e2, this.GetClassAndMethod(MethodBase.GetCurrentMethod(), method));
                }
            }

            try
            {
                Thread?.NewState("Register");

                if (databaseProvider != null)
                {
                    method = $"{nameof(Database)}.{nameof(Database.Register)}";
                    Database.Register(databaseProvider, false);
                    // All is good.
                    this.SetState(StorageState.Ready);
                }
                else
                {
                    this.SetState(StorageState.NeedsRepair);
                }
            }
            catch (Exception e)
            {
                e = Log.UnnestException(e);
                Thread?.Exception(e);
                this.logService.LogException(e, this.GetClassAndMethod(MethodBase.GetCurrentMethod(), method));
                this.SetState(StorageState.NeedsRepair);
            }
            finally
            {
                Thread?.Stop();
            }
        }
Esempio n. 13
0
 /// <summary>
 /// Exception occurred
 /// </summary>
 /// <param name="Ticks">Elapsed ticks.</param>
 /// <param name="Exception">Exception object.</param>
 /// <param name="Thread">Profiler thread generating the event.</param>
 public Exception(long Ticks, System.Exception Exception, ProfilerThread Thread)
     : base(Ticks, Thread)
 {
     this.exception = Exception;
 }