/// <summary>
        ///   Enqueues game related operation requests in the peers current game.
        /// </summary>
        /// <param name = "operationRequest">
        ///   The operation request.
        /// </param>
        /// <param name = "sendParameters">
        ///   The send Parameters.
        /// </param>
        /// <remarks>
        ///   The current for a peer is stored in the peers state property.
        ///   Using the <see cref = "Room.EnqueueOperation" /> method ensures that all operation request dispatch logic has thread safe access to all room instance members since they are processed in a serial order.
        ///   <para>
        ///     Inheritors can use this method to enqueue there custom game operation to the peers current game.
        ///   </para>
        /// </remarks>
        private void HandleChangeGroupsOperation(OperationRequest operationRequest, SendParameters sendParameters)
        {
            if (this.joinStage < JoinStages.PublishingEvents)
            {
                this.OnWrongOperationStage(operationRequest, sendParameters);
                return;
            }

            var changeGroupsOperation = new ChangeGroups(this.Protocol, operationRequest);

            if (this.ValidateOperation(changeGroupsOperation, sendParameters) == false)
            {
                return;
            }

            this.AddOperationToQueue(operationRequest.OperationCode, "game op");

            // enqueue operation into game queue.
            // the operation request will be processed in the games ExecuteOperation method.
            if (this.RoomReference != null)
            {
                this.RoomReference.Room.EnqueueOperation(this, changeGroupsOperation, sendParameters);
                return;
            }

            if (log.IsDebugEnabled)
            {
                log.DebugFormat("Received ChangeGroups operation on peer without a game: p:{0}", this);
            }
        }
 /// <summary>
 /// Register a named control object
 /// </summary>
 /// <param name="id">The named ID of the control</param>
 /// <param name="controlType">Set the type of control</param>
 /// <param name="changeGroupID">Set the control to a change group</param>
 /// <returns>The QSysControl object with the ID</returns>
 public QSysControl Register(string id, QSysControlType controlType, int changeGroupID)
 {
     if (!ChangeGroups.Any(i => i == changeGroupID))
     {
         ChangeGroups.Add(changeGroupID);
         if (this.QSys.Connected)
         {
             this.QSys.Send(string.Format("cgc {0}", changeGroupID));
             this.QSys.Send(string.Format("cgs {0} {1}", changeGroupID, 200));
         }
     }
     this.Controls[id] = new QSysControl(this.QSys, id, controlType, changeGroupID);
     return(this[id]);
 }
        protected virtual void HandleChangeGroupsOperation(
            PlayerPeer peer,
            ChangeGroups changeGroupsRequest,
            SendParameters sendParameters)
        {
            // get the actor who send the operation request
            var actor = GetActorByPeer(peer);

            if (actor == null)
            {
                return;
            }

            actor.RemoveGroups(changeGroupsRequest.Remove);

            if (changeGroupsRequest.Add != null)
            {
                if (changeGroupsRequest.Add.Length > 0)
                {
                    foreach (var groupId in changeGroupsRequest.Add)
                    {
                        ActorGroup group;
                        if (!ActorGroups.TryGetValue(groupId, out group))
                        {
                            group = new ActorGroup(groupId);
                            ActorGroups.Add(groupId, group);
                        }

                        actor.AddGroup(group);
                    }
                }
                else
                {
                    foreach (var group in ActorGroups.Values)
                    {
                        actor.AddGroup(group);
                    }
                }
            }
        }
Example #4
0
        void m_worker_DoWork(object sender, DoWorkEventArgs e)
        {
            // migration instruction status
            int analysisMIStatus            = (int)ChangeStatus.AnalysisMigrationInstruction;
            int pendingStatus               = (int)ChangeStatus.Pending;
            int inProgressStatus            = (int)ChangeStatus.InProgress;
            int pendingConflictDetectStatus = (int)ChangeStatus.PendingConflictDetection;
            int completedStatus             = (int)ChangeStatus.Complete;

            RaisePropertyChangedEvent("CanGetNext", null, null);
            int numToTake = (int)e.Argument;

            m_worker.ReportProgress(-1);

            long lastChangeGroupTaken;

            if (numToTake > 0)
            {
                lastChangeGroupTaken = ChangeGroups.Select(x => x.MigrationInstructions.Id).LastOrDefault();
            }
            else
            {
                lastChangeGroupTaken = ChangeGroups.Select(x => x.MigrationInstructions.Id).FirstOrDefault();
            }

            IQueryable <RTChangeGroup> migrationInstructionsQuery;

            if (lastChangeGroupTaken == 0) // haven't gotten anything yet
            {
                long pendingChangeGroup = (from cg in m_context.RTChangeGroupSet
                                           where cg.SourceUniqueId.Equals(m_oneWaySession.Target.UniqueId) &&
                                           cg.SessionUniqueId.Equals(m_oneWaySession.Session.SessionUniqueId) &&
                                           (cg.Status == (int)ChangeStatus.Pending || cg.Status == (int)ChangeStatus.InProgress) &&
                                           !cg.ContainsBackloggedAction
                                           orderby cg.Id ascending
                                           select cg.Id).FirstOrDefault();
                int lastSessionRunId = 0;
                if (pendingChangeGroup == 0)
                {
                    lastSessionRunId = (from cg in m_context.RTChangeGroupSet
                                        where cg.SourceUniqueId.Equals(m_oneWaySession.Target.UniqueId) &&
                                        cg.SessionUniqueId.Equals(m_oneWaySession.Session.SessionUniqueId) &&
                                        (cg.Status == (int)ChangeStatus.Pending || cg.Status == (int)ChangeStatus.InProgress) &&
                                        !cg.ContainsBackloggedAction
                                        select cg.SessionRun.Id).FirstOrDefault();

                    if (lastSessionRunId == 0)
                    {
                        var lastSessionRunQuery = (from cg in m_context.RTChangeGroupSet
                                                   where cg.SessionUniqueId.Equals(m_oneWaySession.Session.SessionUniqueId) &&
                                                   cg.SourceUniqueId.Equals(m_oneWaySession.Source.UniqueId)
                                                   orderby cg.SessionRun.Id descending
                                                   select cg.SessionRun.Id).Take(Math.Abs(numToTake));
                        if (lastSessionRunQuery.Count() != 0)
                        {
                            lastSessionRunId = lastSessionRunQuery.Min();
                        }
                    }
                }

                migrationInstructionsQuery = from cg in m_context.RTChangeGroupSet
                                             where cg.SourceUniqueId.Equals(m_oneWaySession.Target.UniqueId) &&
                                             cg.SessionUniqueId.Equals(m_oneWaySession.Session.SessionUniqueId) &&
                                             (cg.Status == analysisMIStatus || cg.Status == pendingStatus ||
                                              cg.Status == inProgressStatus || cg.Status == pendingConflictDetectStatus ||
                                              cg.Status == completedStatus) &&
                                             cg.Id >= pendingChangeGroup &&
                                             cg.SessionRun.Id >= lastSessionRunId
                                             select cg;
            }
            else if (numToTake > 0)
            {
                migrationInstructionsQuery = from cg in m_context.RTChangeGroupSet
                                             where cg.SourceUniqueId.Equals(m_oneWaySession.Target.UniqueId) &&
                                             cg.SessionUniqueId.Equals(m_oneWaySession.Session.SessionUniqueId) &&
                                             (cg.Status == analysisMIStatus || cg.Status == pendingStatus ||
                                              cg.Status == inProgressStatus || cg.Status == pendingConflictDetectStatus ||
                                              cg.Status == completedStatus) &&
                                             cg.Id > lastChangeGroupTaken
                                             orderby cg.Id ascending
                                             select cg;
            }
            else
            {
                migrationInstructionsQuery = from cg in m_context.RTChangeGroupSet
                                             where cg.SourceUniqueId.Equals(m_oneWaySession.Target.UniqueId) &&
                                             cg.SessionUniqueId.Equals(m_oneWaySession.Session.SessionUniqueId) &&
                                             (cg.Status == analysisMIStatus || cg.Status == pendingStatus ||
                                              cg.Status == inProgressStatus || cg.Status == pendingConflictDetectStatus ||
                                              cg.Status == completedStatus) &&
                                             cg.Id < lastChangeGroupTaken
                                             orderby cg.Id descending
                                             select cg;
            }

            int migrationInstructionsCount = migrationInstructionsQuery.Count();

            var migrationInstructionsSubset = migrationInstructionsQuery.Take(Math.Abs(numToTake));

            int total;

            if (migrationInstructionsCount < Math.Abs(numToTake))
            {
                total    = migrationInstructionsCount;
                e.Result = false; // do not refresh afterwards
            }
            else
            {
                total    = numToTake;
                e.Result = true; // try to refresh afterwards
            }

            if (numToTake > 0)
            {
                // dt means deltaTables
                var pairs = from mi in migrationInstructionsSubset
                            join dt in m_context.RTChangeGroupSet
                            on mi.ReflectedChangeGroupId equals dt.Id
                            join ca in m_context.RTChangeActionSet
                            on dt.Id equals ca.ChangeGroupId into j
                            orderby dt.Id ascending
                            select new
                {
                    Left  = dt,
                    Right = mi,
                    Count = j.Count()
                };

                int currentProgress = 0;
                int counter         = 0;
                foreach (var entry in pairs)
                {
                    DualChangeGroupViewModel changeGroup = new DualChangeGroupViewModel(entry.Left, entry.Right, entry.Count);
                    if (changeGroup.Bucket > maxBucket)
                    {
                        maxBucket = changeGroup.Bucket;
                        if (ChangeGroups.Count == 0)
                        {
                            minBucket = maxBucket;
                        }
                        else
                        {
                            if (counter > 10)
                            {
                                changeGroup.IsMilestone = true;
                                counter = 0;
                            }
                        }
                    }
                    counter++;
                    m_dispatcher.BeginInvoke(new UpdateProgressDelegate(delegate { ChangeGroups.AddLast(changeGroup); }), changeGroup);
                    currentProgress++;
                    m_worker.ReportProgress((int)((double)currentProgress / (double)total * 100));
                }
            }
            else
            {
                // dt means deltaTables
                var pairs = from mi in migrationInstructionsSubset
                            join dt in m_context.RTChangeGroupSet
                            on mi.ReflectedChangeGroupId equals dt.Id
                            join ca in m_context.RTChangeActionSet
                            on dt.Id equals ca.ChangeGroupId into j
                            orderby dt.Id descending
                            select new
                {
                    Left  = dt,
                    Right = mi,
                    Count = j.Count()
                };

                int currentProgress = 0;
                DualChangeGroupViewModel lastChangeGroup = null;
                int counter = 0;
                foreach (var entry in pairs)
                {
                    DualChangeGroupViewModel changeGroup = new DualChangeGroupViewModel(entry.Left, entry.Right, entry.Count);
                    if (changeGroup.Bucket != 0 && changeGroup.Bucket < minBucket)
                    {
                        minBucket = changeGroup.Bucket;
                        if (lastChangeGroup != null)
                        {
                            if (counter > 10)
                            {
                                lastChangeGroup.IsMilestone = true;
                                counter = 0;
                            }
                        }
                    }
                    counter++;
                    m_dispatcher.BeginInvoke(new UpdateProgressDelegate(delegate { ChangeGroups.AddFirst(changeGroup); }), changeGroup);
                    currentProgress++;
                    m_worker.ReportProgress((int)((double)currentProgress / (double)total * 100));

                    lastChangeGroup = changeGroup;
                }
            }
            m_worker.ReportProgress(100);
        }
Example #5
0
        /// <summary>
        ///   Called for each operation in the execution queue.
        ///   Every <see cref = "Room" /> has a queue of incoming operations to execute.
        ///   Per game <see cref = "ExecuteOperation" /> is never executed multi-threaded, thus all code executed here has thread safe access to all instance members.
        /// </summary>
        /// <param name = "peer">
        ///   The peer.
        /// </param>
        /// <param name = "operationRequest">
        ///   The operation request to execute.
        /// </param>
        /// <param name = "sendParameters">
        ///   The send Parameters.
        /// </param>
        protected override void ExecuteOperation(LitePeer peer, OperationRequest operationRequest, SendParameters sendParameters)
        {
            try
            {
                base.ExecuteOperation(peer, operationRequest, sendParameters);

                if (Log.IsDebugEnabled)
                {
                    Log.DebugFormat("Executing operation {0}", (OperationCode)operationRequest.OperationCode);
                }

                switch ((OperationCode)operationRequest.OperationCode)
                {
                case OperationCode.Join:
                {
                    var joinRequest = new JoinRequest(peer.Protocol, operationRequest);
                    if (peer.ValidateOperation(joinRequest, sendParameters) == false)
                    {
                        return;
                    }

                    if (this.LogQueue.Log.IsDebugEnabled)
                    {
                        this.LogQueue.Add(
                            new LogEntry(
                                "ExecuteOperation: " + (OperationCode)operationRequest.OperationCode,
                                "Peer=" + peer.ConnectionId));
                    }

                    joinRequest.OnStart();
                    this.HandleJoinOperation(peer, joinRequest, sendParameters);
                    joinRequest.OnComplete();
                    break;
                }

                case OperationCode.Leave:
                {
                    var leaveOperation = new LeaveRequest(peer.Protocol, operationRequest);
                    if (peer.ValidateOperation(leaveOperation, sendParameters) == false)
                    {
                        return;
                    }

                    if (this.LogQueue.Log.IsDebugEnabled)
                    {
                        this.LogQueue.Add(
                            new LogEntry(
                                "ExecuteOperation: " + (OperationCode)operationRequest.OperationCode,
                                "Peer=" + peer.ConnectionId));
                    }

                    leaveOperation.OnStart();
                    this.HandleLeaveOperation(peer, leaveOperation, sendParameters);
                    leaveOperation.OnComplete();
                    break;
                }

                case OperationCode.RaiseEvent:
                {
                    var raiseEventOperation = new RaiseEventRequest(peer.Protocol, operationRequest);
                    if (peer.ValidateOperation(raiseEventOperation, sendParameters) == false)
                    {
                        return;
                    }

                    raiseEventOperation.OnStart();
                    this.HandleRaiseEventOperation(peer, raiseEventOperation, sendParameters);
                    raiseEventOperation.OnComplete();
                    break;
                }

                case OperationCode.GetProperties:
                {
                    var getPropertiesOperation = new GetPropertiesRequest(peer.Protocol, operationRequest);
                    if (peer.ValidateOperation(getPropertiesOperation, sendParameters) == false)
                    {
                        return;
                    }

                    getPropertiesOperation.OnStart();
                    this.HandleGetPropertiesOperation(peer, getPropertiesOperation, sendParameters);
                    getPropertiesOperation.OnComplete();
                    break;
                }

                case OperationCode.SetProperties:
                {
                    var setPropertiesOperation = new SetPropertiesRequest(peer.Protocol, operationRequest);
                    if (peer.ValidateOperation(setPropertiesOperation, sendParameters) == false)
                    {
                        return;
                    }

                    setPropertiesOperation.OnStart();
                    this.HandleSetPropertiesOperation(peer, setPropertiesOperation, sendParameters);
                    setPropertiesOperation.OnComplete();
                    break;
                }

                case OperationCode.Ping:
                {
                    peer.SendOperationResponse(new OperationResponse {
                            OperationCode = operationRequest.OperationCode
                        }, sendParameters);
                    break;
                }

                case OperationCode.ChangeGroups:
                {
                    var changeGroupsOperation = new ChangeGroups(peer.Protocol, operationRequest);
                    if (peer.ValidateOperation(changeGroupsOperation, sendParameters) == false)
                    {
                        return;
                    }

                    changeGroupsOperation.OnStart();
                    this.HandleChangeGroupsOperation(peer, changeGroupsOperation, sendParameters);
                    changeGroupsOperation.OnComplete();
                    break;
                }

                default:
                {
                    string message = string.Format("Unknown operation code {0}", (OperationCode)operationRequest.OperationCode);
                    peer.SendOperationResponse(
                        new OperationResponse {
                            OperationCode = operationRequest.OperationCode, ReturnCode = -1, DebugMessage = message
                        }, sendParameters);

                    if (Log.IsWarnEnabled)
                    {
                        Log.Warn(message);
                    }
                }

                break;
                }
            }
            catch (Exception ex)
            {
                Log.Error(ex);
            }
        }