Example #1
0
 private void sendRpcReply(ErlPid from, ErlRef eref, IErlObject reply)
 {
     if (from.Empty)
     {
         return;
     }
     Node.Send(from, ErlTuple.Create(eref, reply));
 }
Example #2
0
        private void threadSpinCore()
        {
            // For Erlang I/O protocol see:
            // http://erlang.org/doc/apps/stdlib/io_protocol.html

            var patterns = new ErlPatternMatcher
            {
                { "{'$gen_call', {~v::pid(), ~v::ref()}, {call, ~v::atom(), ~v::atom(), ~v::list(), ~v}}".ErlArgs(P, R, M, F, A, G),
                  (_p, _t, b, a) => rpcCall(
                      b.Cast <ErlPid>(P), b.Cast <ErlRef>(R),
                      b.Cast <ErlAtom>(M), b.Cast <ErlAtom>(F), b.Cast <ErlList>(A), b[G]) },
                { "{'$gen_cast', {cast, ~v::atom(), ~v::atom(), ~v::list(), ~v}}".ErlArgs(M, F, A, G),
                  (_p, _t, b, a) => rpcCall(
                      ErlPid.Null, ErlRef.Null,
                      b.Cast <ErlAtom>(M), b.Cast <ErlAtom>(F), b.Cast <ErlList>(A), b[G]) },
                { "{_, {~v::pid(), ~v::ref()}, _Cmd}".ErlArgs(P, R),
                  (_p, _t, b, a) =>
                  ErlTuple.Create(b[P], b[R], ErlTuple.Create(ConstAtoms.Error, ConstAtoms.Unsupported)) },
            };

            while (m_Active)
            {
                Tuple <IErlObject, int> res = Self.ReceiveMatch(patterns, 1500);

                switch (res.Item2)
                {
                case -2: /* timeout  */
                    break;

                case -1: /* no match */
                    App.Log.Write(Log.MessageType.Warning,
                                  StringConsts.ERL_INVALID_RPC_REQUEST_ERROR, res.Item1.ToString());
                    break;

                default:
                    if (res.Item1 == null)
                    {
                        break;
                    }
                    var t     = (ErlTuple)res.Item1;
                    var pid   = t.Cast <ErlPid>(0);
                    var eref  = t.Cast <ErlRef>(1);
                    var reply = t[2];
                    sendRpcReply(pid, eref, reply);
                    break;
                }
            }

            App.Log.Write(
                Log.MessageType.Info, StringConsts.ERL_STOPPING_SERVER.Args(Node.NodeName, "RPC"));

            m_Thread = null;
        }
Example #3
0
        private IErlObject rpcCall(ErlPid from, ErlRef eref,
                                   ErlAtom mod, ErlAtom fun, ErlList args, IErlObject groupLeader)
        {
            // We spawn a new task, so that RPC calls wouldn't block the RPC server thread
            Task.Factory.StartNew(() =>
            {
                var type = Type.GetType(mod);

                if (type == null)
                {
                    sendRpcReply(from, eref,
                                 ErlTuple.Create(ConstAtoms.Error, "unknown type: {0}".Args(mod)));
                    return;
                }

                // TODO: add LRU caching
                //var method = type.GetMethod(fun.Value, BindingFlags.Static | BindingFlags.Public);

                string methodName = fun.Value;

                if (args.Count == 0)
                {
                    var pi = type.GetProperty(fun, BindingFlags.Static | BindingFlags.Public);
                    if (pi != null)
                    {
                        try
                        {
                            var result = pi.GetValue(null, null);
                            sendRpcReply(from, eref,
                                         ErlTuple.Create(ConstAtoms.Ok, result.ToErlObject()));
                        }
                        catch (Exception e)
                        {
                            sendRpcReply(from, eref,
                                         ErlTuple.Create(ConstAtoms.Error, new ErlString(e.Message)));
                        };
                        return;
                    }
                }

                var mi = type.GetMethods(BindingFlags.Static | BindingFlags.Public)
                         .Where(m => m.Name == methodName && m.GetParameters().Count() == args.Count)
                         .FirstOrDefault();

                if (mi == null)
                {
                    sendRpcReply(from, eref,
                                 ErlTuple.Create(ConstAtoms.Error, "unknown method: {0}".Args(fun)));
                    return;
                }

                var pars = mi.GetParameters();

                var margs = new object[pars.Length];

                for (int i = 0; i < pars.Length; i++)
                {
                    var par  = pars[i];
                    var val  = args[i];
                    margs[i] = val.AsType(par.ParameterType);
                }

                try
                {
                    var result = mi.Invoke(type, margs);
                    sendRpcReply(from, eref, ErlTuple.Create(ConstAtoms.Ok, result.ToErlObject()));
                }
                catch (Exception e)
                {
                    sendRpcReply(from, eref, ErlTuple.Create(ConstAtoms.Error, new ErlString(e.Message)));
                }
            });
            return((IErlObject)null);
        }