private void NotifyEnterArea(uint originalSenderId, ulong newAreaId) { this.shardRegionArea.Tell(new ObjectEnterAreaCommand() { ObjectId = this.state.ObjectId, AreaId = newAreaId }); if (this.state.LockOwnerId != LOCKNOOWNER) { var lockCommand = new ObjectLockCommand(this.state.ObjectId, this.state.LockOwnerId, this.state.LockTimeout); this.shardRegionArea.Tell(new AreaCommandEnvelope(newAreaId, new ObjectCommandEnvelope(originalSenderId, lockCommand, this.state.ObjectId))); } }
private void Lock(ObjectLockCommand lockCommand) { if (this.state.LockOwnerId != LOCKNOOWNER && lockCommand.LockOwnerId != LOCKNOOWNER && lockCommand.LockOwnerId != this.state.LockOwnerId) { this.Log.Warning("Lock requested from invalid owner. LockOwner {0} LockRequester {1}", this.state.LockOwnerId, lockCommand.LockOwnerId); return; } this.UpdateStatePersistent(lockCommand, (cmd) => { this.ForwardToArea(new ObjectCommandEnvelope(this.state.LockOwnerId, new ObjectLockCommand(this.state.ObjectId, this.state.LockOwnerId, lockCommand.Timeout), this.state.ObjectId)); }); }
public void ActorMustIgnoreAnyNonOwnerCommand() { //setup const uint LOCKOWNER = 9999; const uint NONLOCKOWNER = 8888; var areaRegionProbe = CreateTestProbe(); IActorRef testeeRef = CreateDefaultObjectActor(areaRegionProbe); var cmdLock = new ObjectLockCommand( objectId: DEFAULTOBJECTID, lockOwnerId: LOCKOWNER, timeout: TimeSpan.FromMinutes(2) ); var cmdEnvLock = new ObjectCommandEnvelope(LOCKOWNER, cmdLock, DEFAULTOBJECTID); var cmdUpdatePosition = new ObjectUpdatePositionCommand( DEFAULTOBJECTID, targetPosition: new AVector3 { X = 10.0f, Y = 20.0f, Z = 30.0f, }, targetOrientation: new AQuaternion { X = 40.0f, Y = 50.0f, Z = 60.0f, W = 70.0f, }, startFrameTick: 0, stopFrameTick: 0 ); var cmdEnvUpdatePosition = new ObjectCommandEnvelope(NONLOCKOWNER, cmdUpdatePosition, DEFAULTOBJECTID); //execute testeeRef.Tell(cmdEnvLock); //verify - update position in new are areaRegionProbe.ExpectMsg <AreaCommandEnvelope>(m => { Assert.Equal(CommandType.ObjectLock, m.ObjectCommandEnvelope.Command.Type); Assert.Equal(Locator.GetAreaIdFromWorldPosition(DEFAULTVECTOR), m.ToAreaId); }); //execute testeeRef.Tell(cmdEnvUpdatePosition); areaRegionProbe.ExpectNoMsg(); }
private void NotifyNewSubscriber(IActorRef subscriber) { var createCommand = new ObjectCreateCommand(0, this.state.ObjectId, this.state.ParentObjectId, this.state.OwnerId, this.state.TypeId, this.state.WorldPosition, this.state.WorldOrientation); subscriber.Tell(this.CreateEnvelope(createCommand)); if (this.state.LockOwnerId != LOCKNOOWNER) { var lockCommand = new ObjectLockCommand(this.state.ObjectId, this.state.LockOwnerId, this.state.LockTimeout); subscriber.Tell(this.CreateEnvelope(lockCommand)); subscriber.Tell(this.CreateEnvelope(this.CreateObjectUpdatePositionCommand())); } foreach (var stateValue in this.state.ObjectStateValues) { var stateValueUpdate = new ObjectValueUpdateCommand(this.state.ObjectId, stateValue.Key, stateValue.Value.Data); subscriber.Tell(this.CreateEnvelope(stateValueUpdate)); } }
/// <summary> /// Command handler. Typically validates commands against current state - possibly by communicating with other actors. /// On successful validation, one or more events are derived from command and persisted. /// </summary> /// <param name="message">Message to process.</param> /// <returns>Message is processed.</returns> protected override bool ReceiveCommand(object message) { if (message is SaveSnapshotSuccess) { this.Log.Debug("SaveSnapshotSuccess"); } if (message is SaveSnapshotFailure) { this.Log.Error("SaveSnapshotFailure"); } if (message is RequestStateCommand) { this.RespondState(((RequestStateCommand)message).ReplyTo); return(true); } if (message is ReceiveTimeout) { this.ValidateResetLock(); } if (message is QuorumRequestEnvelope) { var quorumEnvelope = message as QuorumRequestEnvelope; this.ProcessQuorumRequest(quorumEnvelope); } if (message is Terminated) { this.RemoveQuorumActor((Terminated)message); } if (message is ObjectCommandEnvelope) { var objCmd = (ObjectCommandEnvelope)message; uint senderId = objCmd.SenderId; if (this.state.LockOwnerId != 0 && this.state.LockOwnerId != senderId && IsLockProtectedCommand(objCmd.Command.Type)) { this.log.Warning($"[Object:{this.state.ObjectId}] type: {objCmd.Command.Type} invalid lock owner"); return(false); } this.ValidateResetLock(); this.state.TimeStampLastCommand = DateTime.UtcNow; switch (objCmd.Command.Type) { case CommandType.ObjectUpdatePosition: this.UpdateStatePersistent(new ObjectUpdatePositionCommand(objCmd.Command), (cmd) => this.ForwardToArea(objCmd)); break; case CommandType.ObjectValueUpdate: this.UpdateStatePersistent(new ObjectValueUpdateCommand(objCmd.Command), (cmd) => this.ForwardToArea(objCmd)); break; case CommandType.ObjectValueRemove: this.UpdateStatePersistent(new ObjectValueRemoveCommand(objCmd.Command), (cmd) => this.ForwardToArea(objCmd)); break; case CommandType.ObjectCreate: ObjectCreateCommand createCmd = new ObjectCreateCommand(objCmd.Command); this.NotifyEnterArea(senderId, Locator.GetAreaIdFromWorldPosition(this.state.WorldPosition)); this.UpdateStatePersistent(createCmd, (cmd) => this.ForwardToArea(objCmd)); break; case CommandType.ObjectDestroy: this.NotifyLeaveArea(Locator.GetAreaIdFromWorldPosition(this.state.WorldPosition)); this.ForwardToArea(objCmd); this.Self.Tell(PoisonPill.Instance); this.DeleteMessages(this.LastSequenceNr); this.DeleteSnapshots(SnapshotSelectionCriteria.Latest); break; case CommandType.ObjectLock: ObjectLockCommand lockCmd = new ObjectLockCommand(objCmd.Command); this.Lock(lockCmd); break; case CommandType.ObjectUnlock: ObjectUnlockCommand unlockCmd = new ObjectUnlockCommand(objCmd.Command); this.Unlock(unlockCmd); break; default: throw new InvalidOperationException(objCmd.Command.Type.ToString()); } return(true); } if (message is NotifySubscribeObjectExistenceCommand) { NotifySubscribeObjectExistenceCommand cmd = (NotifySubscribeObjectExistenceCommand)message; this.NotifyNewSubscriber(cmd.Subscriber); } this.SetReceiveTimeout(this.state.LockTimeout); return(true); }