Example #1
0
 /// <summary>
 /// Unregister the WmKcd object specified if there are no more references
 /// to it and it is disconnected.
 /// </summary>
 public static void RemoveKcdIfNoRef(WmKcd kcd)
 {
     if (kcd.KwsTree.Count == 0 && kcd.ConnStatus == KcdConnStatus.Disconnected)
     {
         KcdTree.Remove(kcd.KcdID);
     }
 }
Example #2
0
        /// <summary>
        /// Process a KCD connection notice.
        /// </summary>
        private static void ProcessKcdConnectionNotice(KcdConnectionNotice notice)
        {
            Debug.Assert(Wm.KcdTree.ContainsKey(notice.KcdID));
            WmKcd kcd = Wm.KcdTree[notice.KcdID];

            Debug.Assert(kcd.ConnStatus == KcdConnStatus.Connecting ||
                         kcd.ConnStatus == KcdConnStatus.Disconnecting);

            // We do not want the KCD to be connected anymore. Ignore the
            // message.
            if (kcd.ConnStatus == KcdConnStatus.Disconnecting)
            {
                return;
            }

            // The KCD is now connected.
            kcd.ConnStatus   = KcdConnStatus.Connected;
            kcd.MinorVersion = notice.MinorVersion;
            kcd.ClearError(true);

            // Notify every workspace that the KCD is connected. Stop if the KCD
            // state changes while notifications are being sent.
            foreach (Workspace kws in kcd.KwsTree.Values)
            {
                if (kcd.ConnStatus != KcdConnStatus.Connected)
                {
                    break;
                }
                kws.Sm.HandleKcdConnStatusChange(KcdConnStatus.Connected, null);
            }
        }
Example #3
0
 /// <summary>
 /// Clear the errors associated to the KCD specified, reset the number
 /// of failed connection attempts to 0 and request a run of the state
 /// machine, if required. This can be used to force a KCD to reconnect
 /// sooner than usual.
 /// </summary>
 public static void ResetKcdFailureState(WmKcd kcd)
 {
     if (kcd.FailedConnectCount != 0 || kcd.ErrorDate != DateTime.MinValue)
     {
         kcd.ClearError(true);
         RequestRun("cleared KCD error");
     }
 }
Example #4
0
 public KcdQuery(AnpMsg cmd, KcdQueryDelegate callback, WmKcd kcd, Workspace kws)
 {
     Debug.Assert(cmd.ID != 0);
     Cmd      = cmd;
     Callback = callback;
     Kcd      = kcd;
     Kws      = kws;
 }
Example #5
0
File: WmKcd.cs Project: tmbx/kwm-ng
 public KcdQuery(AnpMsg cmd, KcdQueryDelegate callback, WmKcd kcd, Workspace kws)
 {
     Debug.Assert(cmd.ID != 0);
     Cmd = cmd;
     Callback = callback;
     Kcd = kcd;
     Kws = kws;
 }
Example #6
0
        /// <summary>
        /// Handle non-recoverable KCD errors (aside of disconnection notices).
        /// This method should be called when a KCD behaves badly.
        /// </summary>
        public static void HandleTroublesomeKcd(WmKcd kcd, Exception ex)
        {
            // Assign the error to the KCD.
            AssignErrorToKcd(kcd, false);

            // Disconnect the KCD.
            DisconnectKcd(kcd, ex);
        }
Example #7
0
 /// <summary>
 /// Create the WmKcd object specified if it does not exist, and return
 /// a reference to the WmKcd object specified, if any.
 /// </summary>
 public static WmKcd GetOrCreateKcd(KcdIdentifier kcdID)
 {
     if (kcdID.Host == "")
     {
         return(null);
     }
     if (!KcdTree.ContainsKey(kcdID))
     {
         KcdTree[kcdID] = new WmKcd(kcdID);
     }
     return(KcdTree[kcdID]);
 }
Example #8
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);
            }
        }
Example #9
0
 public void Relink(UInt64 internalID, KwsCoreData cd)
 {
     InternalID = internalID;
     Cd         = cd;
     Cd.Relink();
     Wm.KwsTree[InternalID] = this;
     Kcd = Wm.GetOrCreateKcd(Cd.Credentials.KcdID);
     Kcd.KwsTree[InternalID] = this;
     Sm.Relink(this);
     KcdEventHandler.Relink(this);
     KcdLoginHandler.Relink(this);
     Chat.Relink(this);
     Pb.Relink(this);
     Vnc.Relink(this);
     Kfs.Relink(this);
 }
Example #10
0
        /// <summary>
        /// Process an ANP event received from the KCD.
        /// </summary>
        private static void ProcessKcdAnpEvent(WmKcd kcd, AnpMsg msg)
        {
            // Get the external workspace ID referred to by the event.
            UInt64 externalID = msg.Elements[0].UInt64;

            // Locate the workspace.
            Workspace kws = kcd.GetWorkspaceByExternalID(externalID);

            // No such workspace, bail out.
            if (kws == null)
            {
                return;
            }

            // Dispatch the event to its workspace.
            kws.Sm.HandleKcdEvent(msg);
        }
Example #11
0
        /// <summary>
        /// Disconnect a KCD if it is connecting/connected.
        /// </summary>
        private static void DisconnectKcd(WmKcd kcd, Exception ex)
        {
            if (kcd.ConnStatus == KcdConnStatus.Disconnecting ||
                kcd.ConnStatus == KcdConnStatus.Disconnected)
            {
                return;
            }

            // Send a disconnection request to the KCD.
            kcd.ConnStatus = KcdConnStatus.Disconnecting;
            Wm.KcdBroker.RequestKcdDisconnect(kcd.KcdID);

            // Notify the listeners.
            foreach (Workspace kws in kcd.KwsTree.Values)
            {
                kws.Sm.HandleKcdConnStatusChange(KcdConnStatus.Disconnecting, ex);
            }
        }
Example #12
0
        /// <summary>
        /// Remove the workspace object from the workspace manager. Used by the
        /// WM state machine.
        /// </summary>
        public static void RemoveWorkspace(Workspace kws)
        {
            try
            {
                WmKcd kcd = kws.Kcd;

                // Make sure the state is valid.
                Debug.Assert(KwsTree.ContainsKey(kws.InternalID));
                if (kcd != null)
                {
                    Debug.Assert(kcd.KwsTree.ContainsKey(kws.InternalID));
                    Debug.Assert(!kcd.KwsConnectTree.ContainsKey(kws.InternalID));
                }

                // Unregister the workspace from the workspace manager.
                KwsTree.Remove(kws.InternalID);
                if (KwsRemoveTree.ContainsKey(kws.InternalID))
                {
                    KwsRemoveTree.Remove(kws.InternalID);
                }
                if (kcd != null)
                {
                    kcd.CancelKwsKcdQuery(kws);
                    kcd.KwsTree.Remove(kws.InternalID);
                    RemoveKcdIfNoRef(kcd);
                }
                AdjustPublicKwsID();

                // Delete the workspace data.
                kws.PrepareToRemove();
                foreach (KwsApp app in kws.AppTree.Values)
                {
                    app.PrepareToRemove();
                }

                // The WM state has changed.
                Wm.OnStateChange(WmStateChange.Permanent);
            }

            catch (Exception ex)
            {
                KBase.HandleException(ex, true);
            }
        }
Example #13
0
        /// <summary>
        /// Connect a KCD if it is disconnected.
        /// </summary>
        private static void ConnectKcd(WmKcd kcd)
        {
            if (kcd.ConnStatus != KcdConnStatus.Disconnected)
            {
                return;
            }

            // Clear the current error, but not the failed connection count.
            kcd.ClearError(false);

            // Send a connection request.
            kcd.ConnStatus = KcdConnStatus.Connecting;
            Wm.KcdBroker.RequestKcdConnect(kcd.KcdID);

            // Notify the listeners.
            foreach (Workspace kws in kcd.KwsTree.Values)
            {
                kws.Sm.HandleKcdConnStatusChange(KcdConnStatus.Connecting, null);
            }
        }
Example #14
0
        /// <summary>
        /// Process an ANP reply received from the KCD.
        /// </summary>
        private static void ProcessKcdAnpReply(WmKcd kcd, AnpMsg msg)
        {
            // We have no knowledge of the query. Ignore the reply.
            if (!kcd.QueryMap.ContainsKey(msg.ID))
            {
                return;
            }

            // Retrieve and remove the query from the query map.
            KcdQuery query = kcd.QueryMap[msg.ID];

            // Set the reply in the query.
            query.Res = msg;

            // We don't have non-workspace-related replies yet.
            Debug.Assert(query.Kws != null);

            // Dispatch the message to the workspace.
            query.Kws.Sm.HandleKcdReply(query);
            query.Terminate();
        }
Example #15
0
        /// <summary>
        /// Process a KCD disconnection notice.
        /// </summary>
        private static void ProcessKcdDisconnectionNotice(KcdDisconnectionNotice notice)
        {
            Debug.Assert(Wm.KcdTree.ContainsKey(notice.KcdID));
            WmKcd kcd = Wm.KcdTree[notice.KcdID];

            Debug.Assert(kcd.ConnStatus != KcdConnStatus.Disconnected);

            // The KCD died unexpectedly.
            if (kcd.ConnStatus != KcdConnStatus.Disconnecting)
            {
                // Handle the offense.
                if (notice.Ex != null)
                {
                    // Increase the failed connection attempt count if were
                    // connecting.
                    AssignErrorToKcd(kcd, (kcd.ConnStatus == KcdConnStatus.Connecting));
                }
            }

            // The KCD is now disconnected.
            kcd.ConnStatus = KcdConnStatus.Disconnected;

            // Clear the command-reply mappings associated to the KCD.
            kcd.QueryMap.Clear();

            // Notify every workspace that the KCD is disconnected.
            foreach (Workspace kws in kcd.KwsTree.Values)
            {
                kws.Sm.HandleKcdConnStatusChange(KcdConnStatus.Disconnected, notice.Ex);
            }

            // Remove the KCD if we no longer need it.
            Wm.RemoveKcdIfNoRef(kcd);

            // Re-run the state machine, in case we want to reconnect to the KCD
            // or stop.
            RequestRun("KCD disconnected");
        }
Example #16
0
        /// <summary>
        /// Process an ANP reply received from the KCD.
        /// </summary>
        private static void ProcessKcdAnpReply(WmKcd kcd, AnpMsg msg)
        {
            // We have no knowledge of the query. Ignore the reply.
            if (!kcd.QueryMap.ContainsKey(msg.ID)) return;

            // Retrieve and remove the query from the query map.
            KcdQuery query = kcd.QueryMap[msg.ID];

            // Set the reply in the query.
            query.Res = msg;

            // We don't have non-workspace-related replies yet.
            Debug.Assert(query.Kws != null);

            // Dispatch the message to the workspace.
            query.Kws.Sm.HandleKcdReply(query);
            query.Terminate();
        }
Example #17
0
        /// <summary>
        /// Process an ANP event received from the KCD.
        /// </summary>
        private static void ProcessKcdAnpEvent(WmKcd kcd, AnpMsg msg)
        {
            // Get the external workspace ID referred to by the event.
            UInt64 externalID = msg.Elements[0].UInt64;

            // Locate the workspace.
            Workspace kws = kcd.GetWorkspaceByExternalID(externalID);

            // No such workspace, bail out.
            if (kws == null) return;

            // Dispatch the event to its workspace.
            kws.Sm.HandleKcdEvent(msg);
        }
Example #18
0
        /// <summary>
        /// Disconnect a KCD if it is connecting/connected.
        /// </summary>
        private static void DisconnectKcd(WmKcd kcd, Exception ex)
        {
            if (kcd.ConnStatus == KcdConnStatus.Disconnecting ||
                kcd.ConnStatus == KcdConnStatus.Disconnected) return;

            // Send a disconnection request to the KCD.
            kcd.ConnStatus = KcdConnStatus.Disconnecting;
            Wm.KcdBroker.RequestKcdDisconnect(kcd.KcdID);

            // Notify the listeners.
            foreach (Workspace kws in kcd.KwsTree.Values)
                kws.Sm.HandleKcdConnStatusChange(KcdConnStatus.Disconnecting, ex);
        }
Example #19
0
        /// <summary>
        /// Connect a KCD if it is disconnected.
        /// </summary>
        private static void ConnectKcd(WmKcd kcd)
        {
            if (kcd.ConnStatus != KcdConnStatus.Disconnected) return;

            // Clear the current error, but not the failed connection count.
            kcd.ClearError(false);

            // Send a connection request.
            kcd.ConnStatus = KcdConnStatus.Connecting;
            Wm.KcdBroker.RequestKcdConnect(kcd.KcdID);

            // Notify the listeners.
            foreach (Workspace kws in kcd.KwsTree.Values)
                kws.Sm.HandleKcdConnStatusChange(KcdConnStatus.Connecting, null);
        }
Example #20
0
 /// <summary>
 /// Assign an error to a KCD.
 /// </summary>
 private static void AssignErrorToKcd(WmKcd kcd, bool connectFailureFlag)
 {
     kcd.SetError(DateTime.Now, connectFailureFlag);
 }
Example #21
0
 /// <summary>
 /// Unregister the WmKcd object specified if there are no more references
 /// to it and it is disconnected.
 /// </summary>
 public static void RemoveKcdIfNoRef(WmKcd kcd)
 {
     if (kcd.KwsTree.Count == 0 && kcd.ConnStatus == KcdConnStatus.Disconnected)
         KcdTree.Remove(kcd.KcdID);
 }
Example #22
0
 public void Relink(UInt64 internalID, KwsCoreData cd)
 {
     InternalID = internalID;
     Cd = cd;
     Cd.Relink();
     Wm.KwsTree[InternalID] = this;
     Kcd = Wm.GetOrCreateKcd(Cd.Credentials.KcdID);
     Kcd.KwsTree[InternalID] = this;
     Sm.Relink(this);
     KcdEventHandler.Relink(this);
     KcdLoginHandler.Relink(this);
     Chat.Relink(this);
     Pb.Relink(this);
     Vnc.Relink(this);
     Kfs.Relink(this);
 }
Example #23
0
 /// <summary>
 /// Create the WmKcd object specified if it does not exist, and return 
 /// a reference to the WmKcd object specified, if any.
 /// </summary>
 public static WmKcd GetOrCreateKcd(KcdIdentifier kcdID)
 {
     if (kcdID.Host == "") return null;
     if (!KcdTree.ContainsKey(kcdID)) KcdTree[kcdID] = new WmKcd(kcdID);
     return KcdTree[kcdID];
 }
Example #24
0
        /// <summary>
        /// Handle non-recoverable KCD errors (aside of disconnection notices).
        /// This method should be called when a KCD behaves badly.
        /// </summary>
        public static void HandleTroublesomeKcd(WmKcd kcd, Exception ex)
        {
            // Assign the error to the KCD.
            AssignErrorToKcd(kcd, false);

            // Disconnect the KCD.
            DisconnectKcd(kcd, ex);
        }
Example #25
0
 /// <summary>
 /// Clear the errors associated to the KCD specified, reset the number
 /// of failed connection attempts to 0 and request a run of the state 
 /// machine, if required. This can be used to force a KCD to reconnect
 /// sooner than usual.
 /// </summary>
 public static void ResetKcdFailureState(WmKcd kcd)
 {
     if (kcd.FailedConnectCount != 0 || kcd.ErrorDate != DateTime.MinValue)
     {
         kcd.ClearError(true);
         RequestRun("cleared KCD error");
     }
 }
Example #26
0
 /// <summary>
 /// Assign an error to a KCD.
 /// </summary>
 private static void AssignErrorToKcd(WmKcd kcd, bool connectFailureFlag)
 {
     kcd.SetError(DateTime.Now, connectFailureFlag);
 }