コード例 #1
0
ファイル: ErlRpcServer.cs プロジェクト: dotnetchris/nfx
        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;
        }
コード例 #2
0
ファイル: ErlIoServer.cs プロジェクト: mjaric/nfx
 private IErlObject ioProcessRequests(
     ErlPatternMatcher pm, ErlList requests, IErlObject replyAs)
 {
     foreach (var r in requests)
     {
         IErlObject term = r;
         if (pm.Match(ref term, replyAs) < 0)
         {
             return(term);
         }
     }
     return(s_ReplyPattern.Subst(
                new ErlVarBind {
         { RA, replyAs },
         { R, (IErlObject)Tuple.Create(ConstAtoms.Error, ConstAtoms.Request) }
     }));
 }
コード例 #3
0
        public void ErlPatternMatchCollectionTest()
        {
            var state = new KVP();

            var pm = new ErlPatternMatcher
            {
                { 0, "{A::integer(), stop}", (_ctx, p, t, b, _args) => { state = new KVP(p, b); return(t); } },
                { "{A::integer(), status}", (p, t, b, _args) => { state = new KVP(p, b); return(t); } },
                { 1, "{A::integer(), {status, B::atom()}}", (_ctx, p, t, b, _args) => { state = new KVP(p, b); return(t); } },
                { "{A::integer(), {config, B::list()}}", (p, t, b, _args) => { state = new KVP(p, b); return(t); } }
            };

            var term = ErlObject.Parse("{10, stop}");

            Assert.AreEqual(1, pm.Match(ref term));
            Assert.AreEqual(10, state.Value["A"].ValueAsInt);

            term = ErlObject.Parse("{11, status}");
            Assert.AreEqual(2, pm.Match(ref term));
            Assert.AreEqual(11, state.Value["A"].ValueAsInt);

            term = ErlObject.Parse("{12, {status, ~w}}", new ErlAtom("a"));
            Assert.AreEqual(3, pm.Match(ref term));
            Assert.AreEqual(12, state.Value["A"].ValueAsInt);
            Assert.AreEqual("a", state.Value["B"].ValueAsString);

            term = ErlObject.Parse("{13, {config, ~w}}", new ErlList());
            Assert.AreEqual(4, pm.Match(ref term));
            Assert.AreEqual(13, state.Value["A"].ValueAsInt);
            Assert.AreEqual(0, (state.Value["B"] as ErlList).Count);

            term = ErlObject.Parse("{10, exit}");
            Assert.AreEqual(-1, pm.Match(ref term));

            var pts = pm.PatternsToString;

            Assert.AreEqual(
                "[{A::int(),stop},{A::int(),status},{A::int(),{status,B::atom()}},{A::int(),{config,B::list()}}]",
                pts);
        }
コード例 #4
0
ファイル: ErlMbox.cs プロジェクト: PavelTorgashov/nfx
    /// <summary>
    /// Receive a message and match it against a given pattern
    /// </summary>
    /// <param name="pm">Patterns to match the message against</param>
    /// <param name="timeoutMsec">Timeout in milliseconds</param>
    /// <returns>Return a tuple containing the received message and index of the
    /// pattern in the pm instance that was successfully matched.
    /// On timeout the 2nd element of the tuple is -2 and 1st element of the tuple is null.
    /// On unsuccessful match the second element of the tuple is -1</returns>
    public Tuple<IErlObject, int> ReceiveMatch(ErlPatternMatcher pm, int timeoutMsec = -1)
    {
      var m = Receive(timeoutMsec);
      if (m == null) return Tuple.Create<IErlObject, int>(null, -2);

      int n = pm.Match(ref m);
      return Tuple.Create(m, n);
    }
コード例 #5
0
ファイル: ErlRpcServer.cs プロジェクト: vlapchenko/nfx
    private void start(object obj)
    {
      // 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;
    }
コード例 #6
0
ファイル: ErlIoServer.cs プロジェクト: PavelTorgashov/nfx
    private void threadSpinCore()
    {
      // For Erlang I/O protocol see:
      // http://erlang.org/doc/apps/stdlib/io_protocol.html

      var patterns = new ErlPatternMatcher
                {
                    {"{put_chars, ~v::atom(), ~v::string()}".ErlArgs(E, C),
                        (_p, _t, b, a) => ioProcessPutChars(
                            b.Cast<ErlAtom>(E), b.Cast<ErlString>(C), (IErlObject)a[1]) },
                    {"{put_chars, ~v::atom(), ~v::atom(), ~v::atom(), ~v::list()}".ErlArgs(E,M,F,A),
                        (_p, _t, b, a) => ioProcessPutChars(
                            b.Cast<ErlAtom>(E), b.Cast<ErlAtom>(M),
                            b.Cast<ErlAtom>(F), b.Cast<ErlList>(A),
                            (IErlObject)a[1]) },
                    {"{put_chars, ~v::string()}".ErlArgs(C),
                        (_p, _t, b, a) => ioProcessPutChars(
                            ConstAtoms.Latin1, b.Cast<ErlString>(C), (IErlObject)a[1]) },
                    {"{put_chars, ~v::atom(), ~v::atom(), ~v::list()}".ErlArgs(M,F,A),
                        (_p, _t, b, a) => ioProcessPutChars(
                            ConstAtoms.Latin1, b.Cast<ErlAtom>(M),
                            b.Cast<ErlAtom>(F), b.Cast<ErlList>(A),
                            (IErlObject)a[1]) },
                    {"{get_until, ~v::atom(), ~v, ~v::atom(), ~v::atom(), ~v::list()}".ErlArgs(E,P,M,F,A),
                        (_p, _t, b, a) => ioProcessGetUntil(
                            b.Cast<ErlAtom>(E), b[P], b.Cast<ErlAtom>(M), b.Cast<ErlAtom>(F),
                            b.Cast<ErlList>(A), (IErlObject)a[1]) },
                    {"{get_chars, ~v::atom(), ~v, ~v::integer()}".ErlArgs(E,P,N),
                        (_p, _t, b, a) => ioProcessGetChars(
                            b.Cast<ErlAtom>(E), b[P], b.Cast<ErlLong>(N), (IErlObject)a[1]) },
                    {"{get_line, ~v::atom(), ~v}".ErlArgs(E,P),
                        (_p, _t, b, a) => ioProcessGetLine(
                            b.Cast<ErlAtom>(E), b[P], (IErlObject)a[1]) },
                    {"{get_until, ~v, ~v::atom(), ~v::atom(), ~v::list()}".ErlArgs(P,M,F,A),
                        (_p, _t, b, a) => ioProcessGetUntil(
                            ConstAtoms.Latin1, b[P], b.Cast<ErlAtom>(M), b.Cast<ErlAtom>(F),
                            b.Cast<ErlList>(A), (IErlObject)a[1]) },
                    {"{get_chars, ~v, ~v::integer()}".ErlArgs(P,N),
                        (_p, _t, b, a) => ioProcessGetChars(
                            ConstAtoms.Latin1, b[P], b.Cast<ErlLong>(N), (IErlObject)a[1]) },
                    {"{get_line, ~v}".ErlArgs(P),
                        (_p, _t, b, a) => ioProcessGetLine(
                            ConstAtoms.Latin1, b[P], (IErlObject)a[1]) },
                    {"{requests, ~v::list()}".ErlArgs(R),
                        (_p, _t, b, a) => ioProcessRequests(
                            (ErlPatternMatcher)a[0], b.Cast<ErlList>(R), (IErlObject)a[1]) },
                };

      while (m_Active)
      {
        Tuple<IErlObject, ErlVarBind> res = Node.GroupLeader.ReceiveMatch(s_RequestPattern, 1500);

        if (res.Item1 == null) // Timeout
          continue;
        else if (res.Item2 == null) // No match
          App.Log.Write(Log.MessageType.Error,
              StringConsts.ERL_INVALID_IO_REQUEST + res.Item1.ToString(), from: GetType().Name);

        var from = res.Item2.Cast<ErlPid>(F);
        var replyAs = res.Item2[RA];
        var request = res.Item2.Cast<ErlTuple>(R);
        var req = (IErlObject)request;

        if (patterns.Match(ref req, patterns, replyAs) >= 0)
        {
          Node.Send(from, req);
          continue;
        }

        var reply = s_ReplyPattern.Subst(new ErlVarBind { { RA, replyAs }, { R, ConstAtoms.Request } });

        Debug.Assert(reply != null);
        Node.Send(from, reply);
      }

      App.Log.Write(Log.MessageType.Info, StringConsts.ERL_STOPPING_SERVER.Args(Node.NodeLongName, "I/O"));

      m_Thread = null;
    }
コード例 #7
0
ファイル: ErlIoServer.cs プロジェクト: PavelTorgashov/nfx
    private IErlObject ioProcessRequests(
        ErlPatternMatcher pm, ErlList requests, IErlObject replyAs)
    {

      foreach (var r in requests)
      {
        IErlObject term = r;
        if (pm.Match(ref term, replyAs) < 0)
          return term;
      }
      return s_ReplyPattern.Subst(
          new ErlVarBind{
                        {RA, replyAs},
                        {R, (IErlObject)Tuple.Create(ConstAtoms.Error, ConstAtoms.Request)
                    }});
    }
コード例 #8
0
ファイル: ErlIoServer.cs プロジェクト: mjaric/nfx
        private void startIO(object obj)
        {
            // For Erlang I/O protocol see:
            // http://erlang.org/doc/apps/stdlib/io_protocol.html

            var patterns = new ErlPatternMatcher
            {
                { "{put_chars, ~v::atom(), ~v::string()}".ErlArgs(E, C),
                  (_p, _t, b, a) => ioProcessPutChars(
                      b.Cast <ErlAtom>(E), b.Cast <ErlString>(C), (IErlObject)a[1]) },
                { "{put_chars, ~v::atom(), ~v::atom(), ~v::atom(), ~v::list()}".ErlArgs(E, M, F, A),
                  (_p, _t, b, a) => ioProcessPutChars(
                      b.Cast <ErlAtom>(E), b.Cast <ErlAtom>(M),
                      b.Cast <ErlAtom>(F), b.Cast <ErlList>(A),
                      (IErlObject)a[1]) },
                { "{put_chars, ~v::string()}".ErlArgs(C),
                  (_p, _t, b, a) => ioProcessPutChars(
                      ConstAtoms.Latin1, b.Cast <ErlString>(C), (IErlObject)a[1]) },
                { "{put_chars, ~v::atom(), ~v::atom(), ~v::list()}".ErlArgs(M, F, A),
                  (_p, _t, b, a) => ioProcessPutChars(
                      ConstAtoms.Latin1, b.Cast <ErlAtom>(M),
                      b.Cast <ErlAtom>(F), b.Cast <ErlList>(A),
                      (IErlObject)a[1]) },
                { "{get_until, ~v::atom(), ~v, ~v::atom(), ~v::atom(), ~v::list()}".ErlArgs(E, P, M, F, A),
                  (_p, _t, b, a) => ioProcessGetUntil(
                      b.Cast <ErlAtom>(E), b[P], b.Cast <ErlAtom>(M), b.Cast <ErlAtom>(F),
                      b.Cast <ErlList>(A), (IErlObject)a[1]) },
                { "{get_chars, ~v::atom(), ~v, ~v::integer()}".ErlArgs(E, P, N),
                  (_p, _t, b, a) => ioProcessGetChars(
                      b.Cast <ErlAtom>(E), b[P], b.Cast <ErlLong>(N), (IErlObject)a[1]) },
                { "{get_line, ~v::atom(), ~v}".ErlArgs(E, P),
                  (_p, _t, b, a) => ioProcessGetLine(
                      b.Cast <ErlAtom>(E), b[P], (IErlObject)a[1]) },
                { "{get_until, ~v, ~v::atom(), ~v::atom(), ~v::list()}".ErlArgs(P, M, F, A),
                  (_p, _t, b, a) => ioProcessGetUntil(
                      ConstAtoms.Latin1, b[P], b.Cast <ErlAtom>(M), b.Cast <ErlAtom>(F),
                      b.Cast <ErlList>(A), (IErlObject)a[1]) },
                { "{get_chars, ~v, ~v::integer()}".ErlArgs(P, N),
                  (_p, _t, b, a) => ioProcessGetChars(
                      ConstAtoms.Latin1, b[P], b.Cast <ErlLong>(N), (IErlObject)a[1]) },
                { "{get_line, ~v}".ErlArgs(P),
                  (_p, _t, b, a) => ioProcessGetLine(
                      ConstAtoms.Latin1, b[P], (IErlObject)a[1]) },
                { "{requests, ~v::list()}".ErlArgs(R),
                  (_p, _t, b, a) => ioProcessRequests(
                      (ErlPatternMatcher)a[0], b.Cast <ErlList>(R), (IErlObject)a[1]) },
            };

            while (m_Active)
            {
                Tuple <IErlObject, ErlVarBind> res = Node.GroupLeader.ReceiveMatch(s_RequestPattern, 1500);

                if (res.Item1 == null)     // Timeout
                {
                    continue;
                }
                else if (res.Item2 == null)     // No match
                {
                    App.Log.Write(Log.MessageType.Error,
                                  StringConsts.ERL_INVALID_IO_REQUEST + res.Item1.ToString(), from: GetType().Name);
                }

                var from    = res.Item2.Cast <ErlPid>(F);
                var replyAs = res.Item2[RA];
                var request = res.Item2.Cast <ErlTuple>(R);
                var req     = (IErlObject)request;

                if (patterns.Match(ref req, patterns, replyAs) >= 0)
                {
                    Node.Send(from, req);
                    continue;
                }

                var reply = s_ReplyPattern.Subst(new ErlVarBind {
                    { RA, replyAs }, { R, ConstAtoms.Request }
                });

                Debug.Assert(reply != null);
                Node.Send(from, reply);
            }

            App.Log.Write(Log.MessageType.Info, StringConsts.ERL_STOPPING_SERVER.Args(Node.NodeLongName, "I/O"));

            m_Thread = null;
        }