Beispiel #1
0
        /// <summary>
        /// This method can be called by the state machine methods to request
        /// the state machine to run at Deadline. If Deadline is MinValue, the
        /// state machine will be run again immediately.
        /// </summary>
        public static void ScheduleRun(String reason, DateTime deadline)
        {
            // Remember the previous next run date.
            DateTime oldNextRunDate = m_nextRunDate;

            // Update the next run date.
            String ls = "WM run scheduled: " + reason + ".";

            if (deadline != DateTime.MinValue)
            {
                ls += " When: " + deadline + ".";
                if (deadline < m_nextRunDate)
                {
                    m_nextRunDate = deadline;
                }
            }

            else
            {
                ls           += " When: now.";
                m_nextRunDate = DateTime.MinValue;
            }

            KLogging.Log(ls);

            // If we modified the next run date, notify the timer thread,
            // unless we're running inside the SM, in which case we'll call
            // ScheduleTimerEvent() after the state machine has stabilized.
            if (!m_runningFlag && oldNextRunDate != m_nextRunDate)
            {
                ScheduleTimerEvent();
            }
        }
Beispiel #2
0
        /// <summary>
        /// Called to process the messages received by this window.
        /// </summary>
        protected override void WndProc(ref Message m)
        {
            if (m.Msg == KSyscalls.WM_COPYDATA)
            {
                KSyscalls.COPYDATASTRUCT cds = (KSyscalls.COPYDATASTRUCT)m.GetLParam(typeof(KSyscalls.COPYDATASTRUCT));
                int msgID = cds.dwData.ToInt32();

                // This is for us.
                if (msgID == Program.ImportKwsMsgID || msgID == Program.ForegroundMsgID)
                {
                    // Retrieve the path argument. Clone the string to avoid
                    // any potential trouble.
                    String path = cds.lpData.Clone() as String;

                    if (msgID == Program.ForegroundMsgID)
                    {
                        // FIXME.
                        KLogging.Log("Received request to put process in the foreground.");
                    }

                    // This is our import workspace credentials message.
                    else if (msgID == Program.ImportKwsMsgID)
                    {
                        KLogging.Log("Received request to import workspace from window procedure.");

                        // Perform the import.
                        Program.ImportKwsList(path);
                    }
                }
            }

            base.WndProc(ref m);
        }
Beispiel #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();
        }
Beispiel #4
0
        /// <summary>
        /// Handle an ANP event received from the KCD.
        /// </summary>
        public void HandleKcdEvent(AnpMsg msg)
        {
            KLogging.Log("HandleAnpEvent() in kws " + m_kws.InternalID + ", status " + m_cd.MainStatus);

            // This is a permanent event.
            if (msg.ID > 0)
            {
                // Logic problem detected.
                if (msg.ID < m_ks.LastReceivedEventId)
                {
                    BlameKcd(new Exception("received ANP event with bogus ID"));
                    return;
                }

                // Store the event in the database. Mark it as unprocessed.
                m_kws.StoreKAnpEventInDb(msg, KwsAnpEventStatus.Unprocessed);

                // Update the information about the events.
                m_ks.NbUnprocessedEvent++;
                m_ks.LastReceivedEventId = msg.ID;
                m_kws.OnStateChange(WmStateChange.Permanent);
            }

            // If this is a transient event or the only unprocessed event,
            // dispatch it right away if possible. This is done so that single
            // incoming events are processed very quickly instead of waiting
            // for a future workspace state machine run.
            if (msg.ID == 0 ||
                (m_ks.NbUnprocessedEvent == 1 &&
                 !WmKcdState.QuenchFlag &&
                 m_kws.IsOfflineCapable()))
            {
                DispatchKcdEvent(msg);
            }
        }
Beispiel #5
0
        /// <summary>
        /// Process the messages received from the KCD, if any.
        /// </summary>
        private static void ProcessKcdMessages()
        {
            // If we were not notified, bail out quickly.
            if (!WmKcdState.EventFlag)
            {
                return;
            }

            // Clear the notification flag.
            WmKcdState.EventFlag = false;

            // Get the messages.
            List <KcdControlMsg> controlList = new List <KcdControlMsg>();
            List <KcdAnpMsg>     anpList     = new List <KcdAnpMsg>();

            Wm.KcdBroker.GetMessagesForWm(out controlList, out anpList);
            KLogging.Log("ProcessKcdMessages(), anpList.Count = " + anpList.Count);

            // Process the messages.
            foreach (KcdControlMsg m in controlList)
            {
                ProcessKcdControlMsg(m);
            }
            foreach (KcdAnpMsg m in anpList)
            {
                ProcessKcdAnpMsg(m);
            }
        }
Beispiel #6
0
 /// <summary>
 /// This method is called when the workspace manager has stopped.
 /// The WM is serialized and the application is told to quit.
 /// </summary>
 private static void HandlePostStop()
 {
     KLogging.Log("WmSm: " + KwmStrings.Kwm + " has stopped.");
     Wm.MainStatus = WmMainStatus.Stopped;
     Wm.Serialize();
     Program.RequestAppExit();
 }
Beispiel #7
0
        /// <summary>
        /// Called when the login reply is received.
        /// </summary>
        private void HandleConnectKwsReply(KcdQuery query)
        {
            KLogging.Log("Got login reply, kws " + m_kws.InternalID + ", status " + m_kws.Cd.MainStatus);

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

            // This is the standard login reply.
            if (query.Res.Type == KAnp.KANP_RES_KWS_CONNECT_KWS)
            {
                // Get the provided information.
                KwsConnectRes r = new KwsConnectRes(query.Res);
                KLogging.Log(m_currentStep + " login step: " + r.ErrMsg);

                // Dispatch.
                if (r.Code == KAnp.KANP_KWS_LOGIN_OK)
                {
                    HandleConnectKwsSuccess(r);
                }
                else if (r.Code == KAnp.KANP_KWS_LOGIN_BAD_PWD_OR_TICKET)
                {
                    HandleBadPwdOrTicket(r);
                }
                else
                {
                    HandleLoginFailure(TranslateKcdLoginStatusCode(r.Code), new Exception(r.ErrMsg));
                }
            }

            // This is an unexpected reply.
            else
            {
                HandleLoginFailure(KwsLoginResult.MiscKcdError, EAnpException.FromKAnpReply(query.Res));
            }
        }
Beispiel #8
0
        /// <summary>
        /// "Import" a workspace that already exists in the KWM.
        /// </summary>
        private static void ImportExistingKws(Workspace kws, KwsCredentials creds)
        {
            KwsTask task = kws.Cd.CurrentTask;

            KLogging.Log("Import of existing workspace " + kws.InternalID + " with task " + task + " requested.");

            // We can only import workspaces that are stopped or working
            // offline.
            if (task != KwsTask.Stop && task != KwsTask.WorkOffline)
            {
                KLogging.Log("Skipping import due to incompatible task.");
                return;
            }

            // Update the credentials unless they were already accepted.
            if (kws.Cd.KcdState.LoginResult != KwsLoginResult.Accepted)
            {
                KLogging.Log("Updating workspace credentials.");
                creds.PublicFlag   = kws.Cd.Credentials.PublicFlag;
                kws.Cd.Credentials = creds;
            }

            // Make the workspace work online.
            kws.Sm.RequestTaskSwitch(KwsTask.WorkOnline);

            // The workspace state has changed.
            kws.OnStateChange(WmStateChange.Permanent);
        }
Beispiel #9
0
        /// <summary>
        /// Upgrade the database schema if required.
        /// </summary>
        private void UpgradeDb(UInt32 version)
        {
            KLogging.Log("Upgrading database schema from version " + version);

            m_db.BeginTransaction();

            UpdateDbVersion(LatestDbVersion);

            m_db.CommitTransaction();
        }
Beispiel #10
0
        /// <summary>
        /// Called when the login fails with KANP_KWS_LOGIN_BAD_PWD_OR_TICKET.
        /// </summary>
        private void HandleBadPwdOrTicket(KwsConnectRes r)
        {
            // Remember that the workspace is secure and if a password is available.
            m_kws.Cd.Credentials.SecureFlag = r.SecureFlag;
            m_ks.PwdPresentFlag             = r.PwdOnKcdFlag;
            m_kws.OnStateChange(WmStateChange.Permanent);

            // The cached step has failed.
            if (m_currentStep == KwsLoginStep.Cached)
            {
                // Only the cached step was allowed. We're done.
                if (m_loginType == KwsLoginType.Cached)
                {
                    HandleLoginFailure(KwsLoginResult.BadSecurityCreds, new Exception("security credentials refused"));
                    return;
                }

                // We can perform the ticket step.
                if (KwmCfg.Cur.CanLoginOnKps())
                {
                    HandleTicketLoginStep();
                    return;
                }
            }

            // The ticket step has failed.
            else if (m_currentStep == KwsLoginStep.Ticket)
            {
                // Log the ticket refusal string.
                KLogging.Log("Ticket refused: " + r.ErrMsg);
            }

            // There is no password on the KCD.
            if (!m_ks.PwdPresentFlag)
            {
                HandleLoginFailure(KwsLoginResult.BadSecurityCreds,
                                   new Exception("a password must be assigned to you"));
                return;
            }

            // The password provided is bad.
            if (m_currentStep == KwsLoginStep.Pwd)
            {
                // Execute that asynchronously since we want our state to be
                // predictable.
                if (OnSetLoginPwdRefused != null)
                {
                    KBase.ExecInUI(OnSetLoginPwdRefused);
                }
            }

            // We need a password.
            HandlePwdLoginStep();
        }
Beispiel #11
0
        /// <summary>
        /// Import or join a workspace that does not exist in the KWM.
        /// </summary>
        private static void ImportNewKws(KwsCredentials creds)
        {
            KLogging.Log("Importing new workspace " + creds.KwsName + ".");

            // Create the workspace.
            Workspace kws = Wm.CreateWorkspace(creds);

            // Set its main status.
            kws.Cd.MainStatus = KwsMainStatus.Good;

            // Make the workspace work online.
            kws.Sm.RequestTaskSwitch(KwsTask.WorkOnline);
        }
Beispiel #12
0
        /// <summary>
        /// Process an ANP message received from the KCD.
        /// </summary>
        private static void ProcessKcdAnpMsg(KcdAnpMsg m)
        {
            KLogging.Log("ProcessKcdAnpMsg() called");

            // We're stopping. Bail out.
            if (StopFlag)
            {
                return;
            }

            // The KCD specified does not exist. Bail out.
            if (!Wm.KcdTree.ContainsKey(m.KcdID))
            {
                return;
            }

            // The KCD is not connected. Bail out.
            WmKcd kcd = Wm.KcdTree[m.KcdID];

            if (kcd.ConnStatus != KcdConnStatus.Connected)
            {
                return;
            }

            // Process the message according to its type.
            try
            {
                if (m.Msg.Type == KAnp.KANP_RES_FAIL && m.Msg.Elements[0].UInt32 == KAnp.KANP_RES_FAIL_BACKEND)
                {
                    throw new Exception("backend error: " + m.Msg.Elements[1].String);
                }
                else if (m.IsReply())
                {
                    ProcessKcdAnpReply(kcd, m.Msg);
                }
                else if (m.IsEvent())
                {
                    ProcessKcdAnpEvent(kcd, m.Msg);
                }
                else
                {
                    throw new Exception("received unexpected ANP message type (" + m.Msg.Type + ")");
                }
            }

            catch (Exception ex)
            {
                HandleTroublesomeKcd(kcd, ex);
            }
        }
Beispiel #13
0
        /// <summary>
        /// Stop the KMOD thread and kill all pending and executing
        /// transactions.
        /// </summary>
        private void Killall(Exception ex)
        {
            // Get the list of failing transactions and clear the current data
            // structures.
            List <KmodTransaction> list = new List <KmodTransaction>();

            list.AddRange(m_transactionQueue);
            m_transactionQueue.Clear();

            if (m_curTransaction != null)
            {
                list.Add(m_curTransaction);
                m_curTransaction = null;
            }

            // Mark the transactions as failing.
            foreach (KmodTransaction transaction in list)
            {
                transaction.Status = KmodTransactionStatus.Failing;
            }

            // Stop the thread if it is running.
            StopKmodThread();

            // Kill all transactions.
            foreach (KmodTransaction transaction in list)
            {
                if (transaction.Status != KmodTransactionStatus.Failing)
                {
                    continue;
                }
                transaction.Status = KmodTransactionStatus.Finished;
                transaction.Ex     = ex;
                if (ex != null)
                {
                    KLogging.LogException(ex);
                }

                try
                {
                    transaction.Run(KmodTransactionReason.Error);
                }

                catch (Exception ex2)
                {
                    KBase.HandleException(ex2, true);
                }
            }
        }
Beispiel #14
0
 /// <summary>
 /// Mark the KCD as disconnected, add a control message for the KCD in
 /// the control message list and add the KCD to the disconnected list.
 /// </summary>
 private void HandleDisconnectedKcd(KcdThreadHost k, Exception ex)
 {
     if (ex != null)
     {
         KLogging.Log(2, "KCD " + k.KcdID.Host + " exception: " + ex.Message);
     }
     if (k.Tunnel != null)
     {
         k.Tunnel.Disconnect();
     }
     k.ConnStatus = KcdThreadConnStatus.Disconnected;
     k.Ex         = new EAnpExKcdConn();
     m_toWmControlMsgList.Add(new KcdDisconnectionNotice(k.KcdID, k.Ex));
     m_disconnectedList.Add(k);
 }
Beispiel #15
0
        /// <summary>
        /// Create a listening socket and spawn ktlstunnel process.
        /// </summary>
        public void BeginTls(string extraParams)
        {
            IPEndPoint endPoint = new IPEndPoint(IPAddress.Loopback, 0);

            Sock = new Socket(endPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
            Sock.Bind(endPoint);
            Sock.Listen(1);

            // Create a logging dir for ktlstunnel, if it does not exist.
            if (!Directory.Exists(KwmPath.GetKtlstunnelLogFilePath()))
            {
                Directory.CreateDirectory(KwmPath.GetKtlstunnelLogFilePath());
            }

            // Start ktlstunnel as such.
            // ktlstunnel localhost ((IPEndPoint)Listener.LocalEndPoint).Port Host Port [-r host:port]
            String loggingPath  = "-L " + "\"" + KwmPath.GetKtlstunnelLogFilePath() + "ktlstunnel-" + KwmPath.GetLogFileName() + "\" ";
            String loggingLevel = "";

            if (KwmCfg.Cur.KtlstunnelLoggingLevel == 1)
            {
                loggingLevel  = "-l minimal ";
                loggingLevel += loggingPath;
            }
            else if (KwmCfg.Cur.KtlstunnelLoggingLevel == 2)
            {
                loggingLevel  = "-l debug ";
                loggingLevel += loggingPath;
            }

            String startupLine = "\"" + KwmPath.KwmKtlstunnelPath + "\" " +
                                 loggingLevel +
                                 "localhost " + ((IPEndPoint)Sock.LocalEndPoint).Port.ToString() + " " +
                                 Host + " " + Port + " " + extraParams;

            KLogging.Log("Starting ktlstunnel.exe : " + startupLine);

            TunnelProcess = new KProcess(startupLine);
            TunnelProcess.InheritHandles = false;
            TunnelProcess.CreationFlags  = (uint)KSyscalls.CREATION_FLAGS.CREATE_NO_WINDOW;
            TunnelProcess.Start();
        }
Beispiel #16
0
        /// <summary>
        /// Create the initial database schema.
        /// </summary>
        private void CreateSchema()
        {
            KLogging.Log("Creating database schema.");

            m_db.BeginTransaction();

            String s =
                "CREATE TABLE 'db_version' ('version' INT PRIMARY KEY); " +
                "INSERT INTO db_version (version) VALUES (" + LatestDbVersion + "); " +
                "CREATE TABLE 'serialization' ('name' VARCHAR PRIMARY KEY, 'data' BLOB); " +
                "CREATE TABLE 'kws_list' ('kws_id' INT PRIMARY KEY, 'name' VARCHAR); " +
                "CREATE TABLE 'kanp_events' ('kws_id' INT, 'evt_id' INT, 'evt_data' BLOB, 'status' INT); " +
                "CREATE TABLE 'eanp_events' ('kws_id' INT, 'evt_id' INT, 'uuid' BLOB, 'evt_data' BLOB); " +
                "CREATE UNIQUE INDEX 'kanp_events_index_1' ON 'kanp_events' ('kws_id', 'evt_id'); " +
                "CREATE UNIQUE INDEX 'kanp_events_index_2' ON 'kanp_events' ('kws_id', 'status', 'evt_id'); " +
                "CREATE UNIQUE INDEX 'eanp_events_index_1' ON 'eanp_events' ('kws_id', 'evt_id'); ";

            m_db.ExecNQ(s);

            m_db.CommitTransaction();
        }
Beispiel #17
0
        /// <summary>
        /// Run once through the bowels of the state machine.
        /// </summary>
        private static void RunPass()
        {
            // Reset the next run date to the maximum. During the processing of this
            // method, the next run date will lower itself as needed.
            m_nextRunDate = DateTime.MaxValue;

            // We're stopped, nothing to do.
            if (Wm.MainStatus == WmMainStatus.Stopped)
            {
                KLogging.Log("WmSm: " + KwmStrings.Kwm + " is stopped, nothing to do.");
            }

            // Try to stop.
            else if (Wm.MainStatus == WmMainStatus.Stopping && TryStop())
            {
                HandlePostStop();
            }

            // Perform regular processing.
            else
            {
                // Serialize the WM if needed.
                SerializeWmIfNeeded();

                // Process the workspace state machines.
                ProcessKwsStateMachines();

                // Process the workspaces to remove.
                ProcessKwsToRemove();

                // Process the KCDs state changes.
                ProcessKcdState();

                // Recompute the KCD event processing quench.
                RecomputeKcdQuenching();

                // Process the KCD messages.
                ProcessKcdMessages();
            }
        }
Beispiel #18
0
        /// <summary>
        /// Run the workspace manager state machine.
        /// </summary>
        private static void Run(String who)
        {
            KLogging.Log("WmSm: Run() called by " + who);

            try
            {
                // Avoid reentrance.
                if (m_runningFlag)
                {
                    KLogging.Log("WmSm: already running, bailing out.");
                    return;
                }

                m_runningFlag = true;

                // Loop until our state stabilize.
                LockNotif();
                while (WantToRunNow())
                {
                    RunPass();
                }
                UnlockNotif();

                // Schedule the next timer event appropriately.
                ScheduleTimerEvent();

                // We're no longer running the WM.
                m_runningFlag = false;
            }

            // We cannot recover from these errors.
            catch (Exception ex)
            {
                KBase.HandleException(ex, true);
            }
        }
Beispiel #19
0
 /// <summary>
 /// Serialize the object specified and store it under the name
 /// specified in the database.
 /// </summary>
 private static void SerializeObject(String name, Object obj)
 {
     KLogging.Log("Serializing " + name + ".");
 }
Beispiel #20
0
        /// <summary>
        /// Start kmod and connect to it.
        /// </summary>
        private void StartKmod()
        {
            FileStream  file       = null;
            Socket      listenSock = null;
            RegistryKey kwmRegKey  = null;

            try
            {
                // Get the path to the kmod executable in the registry.
                kwmRegKey = KwmReg.GetKwmLMRegKey();
                String Kmod = "\"" + (String)kwmRegKey.GetValue("InstallDir", @"C:\Program Files\Teambox\Teambox Manager") + "\\kmod\\kmod.exe\"";

                // The directory where KMOD will save logs and its database for use with the kwm.
                String KmodDir = KwmPath.GetKmodDirPath();
                Directory.CreateDirectory(KmodDir);

                // Start listening for kmod to connect when it'll be started.
                IPEndPoint endPoint = new IPEndPoint(IPAddress.Loopback, 0);
                listenSock = new Socket(endPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
                listenSock.Bind(endPoint);
                listenSock.Listen(1);
                int port = ((IPEndPoint)listenSock.LocalEndPoint).Port;

                // Start KMOD in debugging mode if our settings say so.
                String debug   = KwmCfg.Cur.KtlstunnelLoggingLevel > 0 ? " -l 3" : "";
                String args    = " -C kmod_connect -p " + port + debug + " -m 20000 -k \"" + KmodDir + "\"";
                String cmdLine = Kmod + args;
                KLogging.Log("About to start kmod.exe: " + cmdLine);
                m_kmodProc = new KProcess(cmdLine);
                m_kmodProc.InheritHandles = false;
                m_kmodProc.CreationFlags  = (uint)KSyscalls.CREATION_FLAGS.CREATE_NO_WINDOW;
                m_kmodProc.Start();

                // Wait for KMOD to connect for about 10 seconds.
                DateTime startTime = DateTime.Now;
                while (true)
                {
                    SelectSockets select = new SelectSockets();
                    select.AddRead(listenSock);
                    SetSelectTimeout(startTime, 10000, select, "no KMOD connection received");
                    Block(select);

                    if (select.InRead(listenSock))
                    {
                        m_kmodSock          = listenSock.Accept();
                        m_kmodSock.Blocking = false;
                        break;
                    }
                }

                // Read the authentication data.
                byte[] authSockData = new byte[32];
                byte[] authFileData = new byte[32];

                startTime = DateTime.Now;
                int nbRead = 0;
                while (nbRead != 32)
                {
                    SelectSockets select = new SelectSockets();
                    select.AddRead(m_kmodSock);
                    SetSelectTimeout(startTime, 2000, select, "no authentication data received");
                    Block(select);
                    int r = KSocket.SockRead(m_kmodSock, authSockData, nbRead, 32 - nbRead);
                    if (r > 0)
                    {
                        nbRead += r;
                    }
                }

                file = File.Open(KmodDir + "\\connect_secret", FileMode.Open);
                file.Read(authFileData, 0, 32);
                if (!KUtil.ByteArrayEqual(authFileData, authSockData))
                {
                    throw new Exception("invalid authentication data received");
                }

                // Set the transport.
                m_transport = new K3pTransport(m_kmodSock);
            }

            finally
            {
                if (file != null)
                {
                    file.Close();
                }
                if (listenSock != null)
                {
                    listenSock.Close();
                }
                if (kwmRegKey != null)
                {
                    kwmRegKey.Close();
                }
            }
        }
Beispiel #21
0
        /// <summary>
        /// Process workspace rebuild if required.
        /// </summary>
        private void ProcessKwsRebuildIfNeeded()
        {
            Debug.Assert(m_rebuildStep == KwsRebuildTaskStep.None);

            if (m_cd.CurrentTask != KwsTask.Rebuild)
            {
                return;
            }

            // Sanity check.
            if (m_cd.MainStatus != KwsMainStatus.RebuildRequired)
            {
                KLogging.Log("cannot execute rebuild task, " + KwmStrings.Kws + " status is not RebuildRequired");
                RequestTaskSwitch(KwsTask.Stop);
                return;
            }

            // We cannot rebuild until the applications are stopped and we're
            // logged out.
            if (m_cd.AppStatus != KwsAppStatus.Stopped || m_ks.LoginStatus != KwsLoginStatus.LoggedOut)
            {
                return;
            }

            // Protect against spurious state changes.
            m_rebuildStep = KwsRebuildTaskStep.InProgress;

            try
            {
                // Ask the workspace to prepare for rebuild.
                m_kws.PrepareToRebuild();
                if (m_rebuildStep != KwsRebuildTaskStep.InProgress)
                {
                    return;
                }

                // Tell the applications to prepare for rebuild.
                foreach (KwsApp app in m_kws.AppTree.Values)
                {
                    app.PrepareToRebuild();
                    if (m_rebuildStep != KwsRebuildTaskStep.InProgress)
                    {
                        return;
                    }
                }
            }

            catch (Exception ex)
            {
                HandleMiscFailure(ex);
                return;
            }

            // We have "rebuilt" the workspace. Update the state.
            m_rebuildStep     = KwsRebuildTaskStep.None;
            m_cd.MainStatus   = KwsMainStatus.Good;
            m_cd.RebuildFlags = 0;
            m_cd.Uuid         = Wm.MakeUuid();
            SetLoginType(KwsLoginType.All);
            m_kws.OnStateChange(WmStateChange.Permanent);

            // Switch to the user task.
            SwitchToUserTask();
        }
Beispiel #22
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();
            }
        }