Example #1
0
        /// <summary>
        /// Called when the login fails for some reason.
        /// </summary>
        public void HandleLoginFailure(Exception ex)
        {
            WmSm.LockNotif();

            Debug.Assert(m_ks.LoginStatus == KwsLoginStatus.LoggingIn);

            // Update our login state.
            UpdateStateOnLogout(ex);

            // The events are out of sync.
            if (m_ks.LoginResult == KwsLoginResult.OOS)
            {
                // Request a rebuild. We have to delete both the cached events and
                // the user data. This is nasty.
                if (m_cd.MainStatus == KwsMainStatus.Good || m_cd.MainStatus == KwsMainStatus.RebuildRequired)
                {
                    m_cd.MainStatus   = KwsMainStatus.RebuildRequired;
                    m_cd.RebuildFlags = KwsRebuildFlag.FlushKcdData | KwsRebuildFlag.FlushLocalData;
                }
            }

            // Make the workspace work offline if required. The core operations
            // may have already marked the workspace for removal.
            if (m_cd.CurrentTask == KwsTask.WorkOnline)
            {
                SetUserTask(KwsTask.WorkOffline);
                RequestTaskSwitch(KwsTask.WorkOffline, ex);
            }

            WmSm.UnlockNotif();
        }
Example #2
0
        /////////////////////////////////////////////
        // Interface methods for external parties. //
        /////////////////////////////////////////////

        /// <summary>
        /// This method must be called by each application when it has started.
        /// </summary>
        public void OnAppStarted()
        {
            // The applications are no longer starting.
            if (m_cd.AppStatus != KwsAppStatus.Starting)
            {
                return;
            }

            // Not all applications have started.
            foreach (KwsApp app in m_kws.AppTree.Values)
            {
                if (app.AppStatus != KwsAppStatus.Started)
                {
                    return;
                }
            }

            WmSm.LockNotif();

            // All applications are started.
            m_cd.AppStatus = KwsAppStatus.Started;

            // Notify the listeners.
            WmSm.QueueNotif(new KwsSmNotifApp(m_kws, m_cd.AppStatus));

            // Let the state machine sort it out.
            RequestRun("Applications started");

            WmSm.UnlockNotif();
        }
Example #3
0
        /// <summary>
        /// This method should be called when an unexpected failure occurs
        /// in the workspace.
        /// </summary>
        public void HandleMiscFailure(Exception ex)
        {
            WmSm.LockNotif();

            KLogging.LogException(ex);

            // We cannot handle failures during task switches. We need the
            // task switches to succeed to recover from failures.
            if (m_taskSwitchFlag)
            {
                KBase.HandleException(ex, true);
            }

            // Increase the severity of the rebuild required if possible.
            if (m_cd.CurrentTask == KwsTask.Rebuild)
            {
                WorsenRebuild(KwsRebuildFlag.FlushKcdData | KwsRebuildFlag.FlushLocalData);
            }

            // Stop the workspace if required.
            SetUserTask(KwsTask.Stop);
            RequestTaskSwitch(KwsTask.Stop, ex);

            // Let the state machine sort it out.
            RequestRun("application failure");

            WmSm.UnlockNotif();
        }
Example #4
0
        /// <summary>
        /// Called when the workspace logs out normally.
        /// </summary>
        public void HandleNormalLogout()
        {
            WmSm.LockNotif();

            Debug.Assert(m_ks.LoginStatus == KwsLoginStatus.LoggingOut);

            // Update our login state.
            UpdateStateOnLogout(null);

            WmSm.UnlockNotif();
        }
Example #5
0
 /// <summary>
 /// Switch the current task to the task specified. Don't call this
 /// outside RequestSwitchTask() unless you know what you are doing.
 /// The state machine will run ASAP to handle the new state.
 /// </summary>
 private void SwitchTask(KwsTask task, Exception ex)
 {
     // The order of the calls is important here.
     WmSm.LockNotif();
     Debug.Assert(m_taskSwitchFlag == false);
     m_taskSwitchFlag = true;
     m_cd.CurrentTask = task;
     StopAppIfNeeded(ex);
     DisconnectFromKcdIfNeeded();
     LogoutIfNeeded();
     StopRebuildIfNeeded();
     UpdateKcdEventUpToDateState();
     m_kws.OnStateChange(WmStateChange.Transient);
     RequestRun("task switch to " + task);
     m_taskSwitchFlag = false;
     WmSm.QueueNotif(new KwsSmNotifTaskSwitch(m_kws, task, ex));
     WmSm.UnlockNotif();
 }
Example #6
0
        /// <summary>
        /// Called when the workspace becomes logged in.
        /// </summary>
        public void HandleLoginSuccess()
        {
            WmSm.LockNotif();

            Debug.Assert(m_ks.LoginStatus == KwsLoginStatus.LoggingIn);

            // We're now logged in.
            m_ks.LoginStatus = KwsLoginStatus.LoggedIn;

            // Update the event up to date state.
            UpdateKcdEventUpToDateState();

            // Notify the listeners.
            WmSm.QueueNotif(new KwsSmNotifKcdLogin(m_kws, m_ks.LoginStatus, null));

            // Let the state machine sort it out.
            RequestRun("Workspace login success");

            WmSm.UnlockNotif();
        }
Example #7
0
        /// <summary>
        /// Request a switch to the task specified, if possible. 'Ex' is
        /// non-null if the task switch is occurring because an error occurred.
        /// </summary>
        public void RequestTaskSwitch(KwsTask task, Exception ex)
        {
            WmSm.LockNotif();

            try
            {
                // Validate.
                if (m_taskSwitchFlag ||
                    task == KwsTask.Stop && !CanStop() ||
                    task == KwsTask.Spawn && !CanSpawn() ||
                    task == KwsTask.Rebuild && !CanRebuild() ||
                    task == KwsTask.WorkOffline && !CanWorkOffline() ||
                    task == KwsTask.WorkOnline && !CanWorkOnline() ||
                    task == KwsTask.DeleteLocally && !CanDeleteLocally() ||
                    task == KwsTask.DeleteRemotely && !CanDeleteRemotely())
                {
                    KLogging.Log("Request to switch to task " + task + " ignored.");
                    return;
                }

                KLogging.Log("Switching to task " + task + ".");

                // Update some state prior to the task switch.
                if (task == KwsTask.Rebuild)
                {
                    m_cd.MainStatus = KwsMainStatus.RebuildRequired;
                    m_rebuildStep   = KwsRebuildTaskStep.None;
                }

                else if (task == KwsTask.WorkOnline)
                {
                    ResetKcdFailureState();
                }

                else if (task == KwsTask.DeleteLocally)
                {
                    m_cd.MainStatus = KwsMainStatus.OnTheWayOut;
                    m_kws.AddToKwsRemoveTree();
                    m_kws.OnStateChange(WmStateChange.Permanent);
                }

                else if (task == KwsTask.DeleteRemotely)
                {
                    ResetKcdFailureState();
                    m_deleteRemotelyStep = KwsDeleteRemotelyStep.ConnectedAndLoggedOut;
                }

                if (task == KwsTask.Spawn ||
                    task == KwsTask.Rebuild ||
                    task == KwsTask.WorkOffline ||
                    task == KwsTask.WorkOnline)
                {
                    m_cd.LastException = null;
                    m_kws.OnStateChange(WmStateChange.Permanent);
                }

                // Perform the task switch, if required.
                if (task != m_cd.CurrentTask)
                {
                    SwitchTask(task, ex);
                }
            }

            catch (Exception ex2)
            {
                KBase.HandleException(ex2, true);
            }

            finally
            {
                WmSm.UnlockNotif();
            }
        }