/// <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); } } } }
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); }
/// <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); } }