private void Unlock(ObjectUnlockCommand unlockCommand) { if (this.state.LockOwnerId != LOCKNOOWNER && unlockCommand.LockOwnerId != LOCKNOOWNER && unlockCommand.LockOwnerId != this.state.LockOwnerId) { this.Log.Warning("Unlock requested from invalid owner. LockOwner {0} UnlockRequester {1}", this.state.LockOwnerId, unlockCommand.LockOwnerId); return; } this.UpdateStatePersistent(unlockCommand, (cmd) => { this.ForwardToArea(new ObjectCommandEnvelope(this.state.LockOwnerId, new ObjectUnlockCommand(this.state.ObjectId, this.state.LockOwnerId), this.state.ObjectId)); }); }
/// <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); }