Esempio n. 1
0
 public void Init(NetContractDescription description, IMessageFactory messageFactory, IOperationExecutor target, ActorKey?actor = null)
 {
     _description    = description;
     _messageFactory = messageFactory;
     _target         = target;
     Actor           = actor;
 }
        public async Task <ActorProxy <TPrimaryNetContract> > GetActor <TPrimaryNetContract>(ActorKey actorKey)
        {
            NetContractDescription desc = Dispatcher.GetContract <TPrimaryNetContract>();
            var proxyKey = new ActorProxyKey(actorKey, desc.TypeId);

            object proxy;

            if (_proxyCache.TryGetValue(proxyKey, out proxy))
            {
                return((ActorProxy <TPrimaryNetContract>)proxy);
            }

            IOperationExecutor operationExecutor;

            if (actorKey.OwnerNodeId == Id) //local actor
            {
                Actor actor;
                Repository.TryGet(actorKey.LocalActorId, out actor);
                operationExecutor = actor;
            }
            else
            {
                operationExecutor = await GetNodePeer(actorKey.OwnerNodeId);
            }

            return((ActorProxy <TPrimaryNetContract>)_proxyCache.GetOrAdd(proxyKey,
                                                                          (actorId) => new ActorProxy <TPrimaryNetContract>(
                                                                              (TPrimaryNetContract)(object)Dispatcher.CreateProxy(Dispatcher.GetContractId(typeof(TPrimaryNetContract)), MessageFactory, operationExecutor, actorKey),
                                                                              actorKey)));
        }
        public void RegisterActorCoordinatorFor <TPrimaryNetContract>(IActorCoordinator coordinator)
        {
            NetContractDescription desc = Dispatcher.GetContract <TPrimaryNetContract>();

            coordinator.Init(this, desc.TypeId);
            _actorCoordinatorsByPrimaryContractId.Add(desc.TypeId, coordinator);
        }
        public async Task DispatchOperationToActor(uint actorLocalId, Message msg, NetPeer peer, bool externalCall)
        {
            try
            {
                Log.Debug("Dispatching {0} from {1} {2}", msg, peer, actorLocalId);
                NetContractDescription desc = Dispatcher.GetContractForMessage(msg.Id);
                if (desc == null)
                {
                    Log.Debug("Dispatching {0} from {1} {2} : contract unknown", msg, peer, actorLocalId);
                    return;
                }
                if (externalCall && !desc.AllowExternalConnections)
                {
                    Log.Debug("Dispatching {0} from {1} {2} : this actor doesn't allow external calls", msg, peer, actorLocalId);
                    return;
                }

                Actor actor;
                if (Repository.TryGet(actorLocalId, out actor))
                {
                    if (msg.GetHeader <OperationHeader>() != null)
                    {
                        Message reply = await((IOperationExecutor)actor).ExecuteOperation(new OperationContext(msg, peer));
                        peer.Reply(msg, reply);

                        Log.Debug("Dispatched {0} from {1} {2} : sending back reply {3}", msg, peer, actorLocalId, reply);
                    }
                    else
                    {
                        ((IOperationExecutor)actor).ExecuteOneWayOperation(new OperationContext(msg, peer));
                    }
                }
                else
                {
                    peer.ReplyWithError(msg, (ushort)BasicErrorCode.NonExistentActor, "Actor not present on this node");
                    Log.Debug("Dispatching {0} from {1} {2} : actor does not exist", msg, peer, actorLocalId);
                }
            }
            catch (InvalidInput iex)
            {
                Log.Info(iex.ToString());
                peer.ReplyWithError(msg, iex.ErrorCode, iex.Message);
            }
            catch (Exception ex)
            {
                Log.ErrorException(string.Format("Error on Dispatching {0} from {1} to {2}", msg, peer, actorLocalId), ex);
            }
            finally
            {
                MessageFactory.Free(msg);
            }
        }
        public NetContractHandler(IOperationDispatcher dispatcher, uint contractId, object implementer)
        {
            Implementer   = implementer;
            ServiceTypeId = contractId;
            Type implementerType           = implementer.GetType();
            NetContractDescription desc    = dispatcher.GetContract(contractId);
            InterfaceMapping       mapping = implementerType.GetInterfaceMap(desc.ContractType);

            foreach (NetOperationDescription operation in desc.Operations)
            {
                var handlerAttr = mapping.TargetMethods.First(m => m.Name == operation.Name).GetAttribute <NetOperationHandlerAttribute>();
                _handlerAttributes.Add(operation.RequestMessageId, handlerAttr ?? new NetOperationHandlerAttribute());
            }
        }
        public async Task <TNetContract> GetProxy <TNetContract>(uint?localActorId = null)
        {
            await Node.Fiber.ContinueOn().ConfigureAwait(false);

            NetContractDescription contractDesc = Node.Dispatcher.GetContract <TNetContract>();
            var      proxyKey = new ActorProxyKey(new ActorKey(0, localActorId ?? 0), contractDesc.TypeId);
            NetProxy proxy;

            if (!_proxyCache.TryGetValue(proxyKey, out proxy))
            {
                proxy = Node.Dispatcher.CreateProxy(contractDesc.TypeId, MessageFactory, this, localActorId.HasValue ? proxyKey.ActorKey : (ActorKey?)null);
                _proxyCache.Add(proxyKey, proxy);
            }

            return((TNetContract)(object)proxy);
        }
        private void OnClientMessage(Message msg)
        {
            Log.Debug("Received " + msg);
            try
            {
                NetContractDescription contractDesc = Node.Dispatcher.GetContractForMessage(msg.Id);

                var actorHeader = msg.GetHeader <ActorHeader>();
                if (actorHeader != null)
                {
                    Node.DispatchOperationToActor(actorHeader.ActorLocalId, msg, this, true);
                }
                else //by default operations are handled by client associated peer
                {
                    NetContractHandler handler;
                    if (_handlersByNetContractId.TryGetValue(contractDesc.TypeId, out handler))
                    {
                        LockType lockType = handler.GetLockTypeForOperation(msg);
                        Log.Debug("Dispatching {0} to client peer", msg);
                        if (lockType == LockType.None)
#pragma warning disable 4014
                        {
                            //for this lock level we really don't wait for any results
                            DispatchAndReplyAsync(handler.Implementer, msg);
                        }
#pragma warning restore 4014
                        else
                        {
                            Fiber.ProcessAsync(() => DispatchAndReplyAsync(handler.Implementer, msg), lockType);
                        }
                    }
                    else
                    {
                        Log.Debug("Skipping {0} because no handler is present", msg);
                        MessageFactory.Free(msg);
                    }
                }
            }
            catch (Exception ex)
            {
                MessageFactory.Free(msg);
                Log.Error("Channel will be closed after: " + ex);
                Channel.Close();
            }
        }
        public IActorCoordinator GetCoordinator <TPrimaryNetContract>()
        {
            NetContractDescription desc = Dispatcher.GetContract <TPrimaryNetContract>();

            if (!desc.IsPrimary)
            {
                throw new Exception("You can access Coordinator or Actor only by Primary contract");
            }

            IActorCoordinator coordinator;

            if (!_actorCoordinatorsByPrimaryContractId.TryGetValue(desc.TypeId, out coordinator))
            {
                throw new Exception("Can't find coordinator for actor group with primary contract " + desc.ContractType.Name);
            }

            return(coordinator);
        }
        public void RegisterService(NetContractDescription desc)
        {
            Contract.Requires(desc != null);

            _descByTypeId.Add(desc.TypeId, desc);
            _contractIdByContractType.Add(desc.ContractType, desc.TypeId);

            foreach (var operation in desc.Operations)
            {
                _descByMessageId.Add(operation.RequestMessageId, desc);
                if (operation.ReplyMessageId.HasValue)
                {
                    _descByMessageId.Add(operation.ReplyMessageId.Value, desc);
                }
                _dispatcherByMsgId.Add(operation.RequestMessageId, operation.Dispatch);
            }

            Log.Info("Registered Entity<contractType:{0}, typeId:{1}>", desc.ContractType, desc.TypeId);
        }
        protected void OnMessage(Message msg)
        {
            NetContractDescription contractDesc = Node.Dispatcher.GetContractForMessage(msg.Id);
            object handler;

            if (_handlersByNetContractId.TryGetValue(contractDesc.TypeId, out handler))
            {
                //NOTE: doesnt support server->client request-reply, only one way notifications that's why Task is not awaited
                Task <Message> task = Node.Dispatcher.Dispatch(handler, msg);
                if (task.Status != TaskStatus.RanToCompletion)
                {
                    Log.Warn("Client supports only one way callback you should never try to return something back from client to server");
                }
            }
            else
            {
                Log.Warn("Handler for {0} is unregistered", msg);
            }

            MessageFactory.Free(msg);
        }
        public OperationDispatcher(IMessageFactory msgfactory, IEnumerable <NetProxy> importedProxies)
        {
            Contract.Requires(importedProxies != null);
            Contract.Requires(msgfactory != null);

            _messageFactory = msgfactory;

            foreach (var proxy in importedProxies)
            {
                Type type = proxy.GetType();
                if (type.ContainsAttribute <NetProxyAttribute>())
                {
                    var proxyAttr    = type.GetAttribute <NetProxyAttribute>();
                    var contractAttr = proxyAttr.ContractType.GetAttribute <NetContractAttribute>();

                    var operations = new List <NetOperationDescription>();
                    foreach (var method in type.GetMethods().Where(x => x.ContainsAttribute <NetOperationDispatcherAttribute>()))
                    {
                        var     opAttr  = method.GetAttribute <NetOperationDispatcherAttribute>();
                        Message request = (Message)FormatterServices.GetUninitializedObject(opAttr.RequestMessage);
                        uint?   replyId = null;
                        if (opAttr.ReplyMessage != null)
                        {
                            replyId = ((Message)FormatterServices.GetUninitializedObject(opAttr.ReplyMessage)).Id;
                        }
                        var opDesc = new NetOperationDescription(
                            method.Name, request.Id, replyId, (Func <IMessageFactory, object, Message, Task <Message> >)Delegate.CreateDelegate(
                                typeof(Func <IMessageFactory, object, Message, Task <Message> >), method));
                        operations.Add(opDesc);
                    }

                    var desc = new NetContractDescription(proxyAttr.ContractTypeId,
                                                          proxyAttr.ContractType, type, contractAttr, operations);
                    RegisterService(desc);
                }
            }
        }
 public void Init(NetContractDescription description, IMessageFactory messageFactory, IOperationExecutor target, ActorKey? actor = null)
 {
     _description = description;
     _messageFactory = messageFactory;
     _target = target;
     Actor = actor;
 }
 public EntityDomainDescriptionTests()
 {
     _protocolDesc = new OperationDispatcher(Substitute.For<IMessageFactory>(),
         new NetProxy[] { new ISomeServiceProxy() });
     _contractDesc = _protocolDesc.GetContract(ServiceTypeId);
 }