示例#1
0
        public void ErlVarBindTest()
        {
            var bind = new ErlVarBind
            {
                { new ErlVar("A", ErlTypeOrder.ErlLong), 10 },
                { new ErlVar("B", ErlTypeOrder.ErlAtom), "abc" },
                { "C", ErlTypeOrder.ErlDouble, 5 }
            };

            Assert.AreEqual((IErlObject)(new ErlLong(10)), bind["A"]);
            Assert.AreEqual((IErlObject)(new ErlAtom("abc")), bind["B"]);
            Assert.AreEqual((IErlObject)(new ErlDouble(5.0)), bind["C"]);

            var term = NFX.Erlang.ErlObject.Parse("{ok, {A::int(), [sasha, B::atom(), C::float()]}}");
            var set  = term.Visit(new SortedSet <ErlVar>(), (a, o) => { if (o is ErlVar)
                                                                        {
                                                                            a.Add((ErlVar)o);
                                                                        }
                                                                        return(a); });

            IErlObject res = null;

            Assert.IsTrue(term.Subst(ref res, bind));
            Assert.AreEqual("{ok, {10, [sasha, abc, 5.0]}}".ToErlObject(), res);
        }
示例#2
0
    private void process(IQueable msg)
    {
      try
      {
        if (msg is ErlException)
        {
          this.Mailbox.DeliverError(this, (ErlException)msg);
          return;
        }
        var erlMsg  = msg as ErlMsg;

        if (erlMsg == null)
          throw new ErlException("Invalid message type: " + msg.GetType());

        var map     = ((ErlDataStore)Store).Map;
        var binding = new ErlVarBind();

        //{Schema, ChangeType :: $d | $w, [{schema, Flds...}]}
        if (erlMsg.Msg==null ||
           !erlMsg.Msg.Match(SUBSCRIPTION_MSG_PATTERN, binding))
          return;

        var schemaName = ((ErlAtom)binding[SCHEMA]).Value;
        var op         = ((ErlByte)binding[TYPE]).Value;
        var rows       = ((ErlList)binding[ROWS]).Value;

        var schema = map.GetCRUDSchemaForName(schemaName);

        foreach(var rowTuple in rows.Cast<ErlTuple>())
        {
          var row  = map.ErlTupleToRow(schemaName, rowTuple, schema);
          var ctp  = op == 'd' ? RowChangeType.Delete : RowChangeType.Upsert;
          var data = new RowChange(ctp, row, null);
          this.Mailbox.Deliver(this, data);
        }
      }
      catch(Exception err)
      {
        App.Log.Write(
          new Log.Message
          {
            Type = Log.MessageType.Error,
            Topic = CoreConsts.ERLANG_TOPIC,
            From = "{0}.process()".Args(GetType().Name),
            Text = err.ToMessageWithType(),
            Exception = err 
          }
        );
      }
    }
示例#3
0
        public void ErlByteTest()
        {
            var t = new ErlByte(10);

            Assert.IsTrue(t.Equals(new ErlByte(10)));
            Assert.AreEqual(t, new ErlByte(10));
            Assert.IsTrue(new ErlByte(1).CompareTo(t) < 0);
            Assert.AreEqual(10, t.Value);
            Assert.AreEqual(10, t.ValueAsInt);
            Assert.AreEqual(10, t.ValueAsLong);
            Assert.AreEqual("10", t.ToString());
            Assert.IsTrue(t.IsScalar);
            Assert.AreEqual(ErlTypeOrder.ErlByte, t.TypeOrder);

            Assert.IsTrue(t.Matches(new ErlByte(10)));
            Assert.AreEqual(new ErlVarBind(), t.Match(new ErlByte(10)));

            Assert.DoesNotThrow(() => { var x = t.ValueAsObject; });
            Assert.AreEqual(10, t.ValueAsInt);
            Assert.AreEqual(10, t.ValueAsLong);
            Assert.AreEqual(10, t.ValueAsDecimal);
            Assert.Throws <ErlIncompatibleTypesException>(() => { var x = t.ValueAsDateTime; });
            Assert.Throws <ErlIncompatibleTypesException>(() => { var x = t.ValueAsTimeSpan; });
            Assert.AreEqual(10.0, t.ValueAsDouble);
            Assert.AreEqual("10", t.ValueAsString);
            Assert.AreEqual(true, t.ValueAsBool);
            Assert.AreEqual('\n', t.ValueAsChar);
            Assert.Throws <ErlIncompatibleTypesException>(() => { var x = t.ValueAsByteArray; });

            IErlObject temp = null;

            Assert.IsFalse(t.Subst(ref temp, new ErlVarBind()));
            Assert.AreEqual(10, t.Visit(0, (acc, o) => o.ValueAsInt));

            char    n = (char)t; Assert.AreEqual('\n', n);
            byte    m = t; Assert.AreEqual(10, m);
            ErlByte b = 10; Assert.AreEqual(10, b.Value);
            ErlByte k = (ErlByte)10; Assert.AreEqual(10, k.Value);
            ErlByte z = (ErlByte)'\n'; Assert.AreEqual(10, k.Value);

            {
                var bind = new ErlVarBind();
                Assert.IsTrue(b.Match(new ErlLong(10), bind));
                Assert.IsTrue(new ErlLong(10).Match(b, bind));
                b = 111;
                Assert.IsTrue(b.Match(new ErlLong(111), bind));
                Assert.IsTrue(new ErlLong(111).Match(b, bind));
            }
        }
示例#4
0
        public void ErlTestFormatVariable()
        {
            var cases = new Dictionary <string, ErlTypeOrder> {
                { "B", ErlTypeOrder.ErlObject },
                { "B::int()", ErlTypeOrder.ErlLong },
                { "B::integer()", ErlTypeOrder.ErlLong },
                { "B::string()", ErlTypeOrder.ErlString },
                { "B::atom()", ErlTypeOrder.ErlAtom },
                { "B::float()", ErlTypeOrder.ErlDouble },
                { "B::double()", ErlTypeOrder.ErlDouble },
                { "B::binary()", ErlTypeOrder.ErlBinary },
                { "B::bool()", ErlTypeOrder.ErlBoolean },
                { "B::boolean()", ErlTypeOrder.ErlBoolean },
                { "B::byte()", ErlTypeOrder.ErlByte },
                { "B::char()", ErlTypeOrder.ErlByte },
                { "B::list()", ErlTypeOrder.ErlList },
                { "B::tuple()", ErlTypeOrder.ErlTuple },
                { "B::pid()", ErlTypeOrder.ErlPid },
                { "B::ref()", ErlTypeOrder.ErlRef },
                { "B::reference()", ErlTypeOrder.ErlRef },
                { "B::port()", ErlTypeOrder.ErlPort }
            };

            foreach (var p in cases)
            {
                IErlObject o = ErlObject.Parse(p.Key);
                Assert.IsInstanceOf(typeof(ErlVar), o);
                Assert.AreEqual(p.Value, ((ErlVar)o).ValueType);
            }

            var pat1 = ErlObject.Parse("{A::char(), B::tuple(), C::float(), D::list(), [E::string(), F::int()], G::bool()}");
            var obj1 = ErlObject.Parse("{$a, {1,2,3}, 10.0, [5,6], [\"abc\", 190], true}");

            var binding = new ErlVarBind();

            Assert.IsTrue(pat1.Match(obj1, binding)); // Match unbound variables
            Assert.IsTrue(pat1.Match(obj1, binding)); // Match bound variables

            var obj2 = ErlObject.Parse("{$a, {1,2,3}, 20.0, [5,6], [\"abc\", 190], true}");

            Assert.IsFalse(pat1.Match(obj2, binding)); // Match bound variables

            binding.Clear();

            var obj3 = ErlObject.Parse("{$a, {1,2,3}, 10.0, [5,6], [\"abc\", bad], false}");

            Assert.IsFalse(pat1.Match(obj3, binding));
        }
        private void checkForError(IErlObject pattern, IErlObject response, ErlVarBind bind, int reqID)
        {
            if (bind != null)
            {
                return;
            }

            bind = response.Match(pattern);
            if (bind == null)
            {
                throw new ErlDataAccessException(StringConsts.ERL_DS_INVALID_RESP_PROTOCOL_ERROR + "invalid error response pattern", new Exception(response.ToString()));
            }

            var gotReqID = bind[ATOM_ReqID].ValueAsLong;

            if (gotReqID != reqID)
            {
                throw new ErlDataAccessException(StringConsts.ERL_DS_INVALID_RESP_PROTOCOL_ERROR + "unexpected transaction ID (expected={0}, got={1})".Args(reqID, gotReqID));
            }

            var ecode = bind[ATOM_Code].ValueAsInt;
            var rmsg  = bind[ATOM_Msg];
            var emsg  = rmsg.TypeOrder == ErlTypeOrder.ErlString || rmsg.TypeOrder == ErlTypeOrder.ErlAtom
                  ? rmsg.ValueAsString
                  : rmsg.ToString();

            Exception error;

            switch (ecode)
            {
            case INVALID_SUBSCRIPTION_REQUEST_EXCEPTION:
                error = new NFX.DataAccess.CRUD.Subscriptions.InvalidSubscriptionRequestException(emsg, null);
                break;

            case -1:
                error = new ErlDataAccessException("Remote error message: {0}".Args(emsg));
                break;

            default:
                error = new ErlDataAccessException("Remote error code {0}. Message: {1}".Args(ecode, emsg));
                break;
            }

            throw error;
        }
示例#6
0
        public void ErlTestPatternMatch()
        {
            {
                var        binding = new ErlVarBind();
                IErlObject obj     = ErlObject.Parse("{snapshot, x12, []}");
                IErlObject pat     = ErlObject.Parse("{snapshot, N, L}");

                Assert.IsTrue(pat.Match(obj, binding));
                ErlAtom n = binding.Cast <ErlAtom>(N);
                ErlList l = binding.Cast <ErlList>(L);
                Assert.IsNotNull(n);
                Assert.IsNotNull(l);
                Assert.IsTrue(l.Count == 0);
            }
            {
                IErlObject pat = ErlObject.Parse("{test, A, B, C}");
                IErlObject obj = ErlObject.Parse("{test, 10, a, [1,2,3]}");

                var binding = new ErlVarBind();
                Assert.IsTrue(pat.Match(obj, binding));
                Assert.AreEqual(3, binding.Count);
                Assert.AreEqual(10, binding.Cast <ErlLong>(A));
                Assert.AreEqual("a", binding.Cast <ErlAtom>(B).ValueAsString);
                Assert.AreEqual("[1,2,3]", binding["C"].ToString());
            }

            {
                var        binding = new ErlVarBind();
                IErlObject obj     = ErlObject.Parse("[1,a,$b,\"xyz\",{1,10.0},[]]");
                IErlObject pat     = ErlObject.Parse("[A,B,C,D,E,F]");

                Assert.IsTrue(pat.Match(obj, binding));
                Assert.IsNotNull(binding.Cast <ErlLong>(A));
                Assert.IsNotNull(binding.Cast <ErlAtom>(B));
                Assert.IsNotNull(binding.Cast <ErlByte>(C));
                Assert.IsNotNull(binding.Cast <ErlString>(D));
                Assert.IsNotNull(binding.Cast <ErlTuple>(E));
                Assert.IsNotNull(binding.Cast <ErlList>(F));

                Assert.IsTrue(binding.Cast <ErlTuple>(E).Count == 2);
                Assert.IsTrue(binding.Cast <ErlList>(F).Count == 0);
            }

            IErlObject pattern = ErlObject.Parse("{test, T}");
            string     exp     = "{test, ~w}";
            {
                var        binding = new ErlVarBind();
                IErlObject obj     = ErlObject.Parse(exp, (int)3);
                Assert.IsTrue(pattern.Match(obj, binding));
                Assert.AreEqual(3, binding.Cast <ErlLong>(T));
            }
            {
                var        binding = new ErlVarBind();
                IErlObject obj     = ErlObject.Parse(exp, (long)100);
                Assert.IsTrue(pattern.Match(obj, binding));
                Assert.AreEqual(100, binding.Cast <ErlLong>(T));
            }
            {
                var        binding = new ErlVarBind();
                IErlObject obj     = ErlObject.Parse(exp, 100.0);
                Assert.IsTrue(pattern.Match(obj, binding));
                Assert.AreEqual(100.0, binding.Cast <ErlDouble>(T).ValueAsDouble);
            }
            {
                var        binding = new ErlVarBind();
                IErlObject obj     = ErlObject.Parse(exp, "test");
                Assert.IsTrue(pattern.Match(obj, binding));
                Assert.AreEqual("test", binding.Cast <ErlString>(T).ValueAsString);
            }
            {
                var        binding = new ErlVarBind();
                IErlObject obj     = ErlObject.Parse(exp, true);
                Assert.IsTrue(pattern.Match(obj, binding));
                Assert.AreEqual(true, binding.Cast <ErlBoolean>(T).ValueAsBool);
            }
            {
                var        binding = new ErlVarBind();
                IErlObject obj     = ErlObject.Parse(exp, 'c');
                Assert.IsTrue(pattern.Match(obj, binding));
                Assert.AreEqual((byte)'c', binding.Cast <ErlByte>(T).ValueAsInt);
            }
            {
                var        binding = new ErlVarBind();
                var        pid     = new ErlPid("tmp", 1, 2, 3);
                IErlObject obj     = ErlObject.Parse(exp, pid as IErlObject);
                Assert.IsTrue(pattern.Match(obj, binding));
                Assert.AreEqual(pid, binding.Cast <ErlPid>(T));
                Assert.AreEqual(pid, binding.Cast <ErlPid>(T).Value);

                obj = ErlObject.Parse(exp, pid);
                Assert.IsTrue(pattern.Match(obj, binding));
                Assert.AreEqual(pid, binding.Cast <ErlPid>(T).Value);
            }
            {
                var        binding = new ErlVarBind();
                var        port    = new ErlPort("tmp", 1, 2);
                IErlObject obj     = ErlObject.Parse(exp, port);
                Assert.IsTrue(pattern.Match(obj, binding));
                Assert.AreEqual(port, binding.Cast <ErlPort>(T));
                Assert.AreEqual(port, binding.Cast <ErlPort>(T).Value);
            }
            {
                var        binding   = new ErlVarBind();
                var        reference = new ErlRef("tmp", 1, 0, 0, 2);
                IErlObject obj       = ErlObject.Parse(exp, reference);
                Assert.IsTrue(pattern.Match(obj, binding));
                Assert.AreEqual(reference, binding.Cast <ErlRef>(T));
                Assert.AreEqual(reference, binding.Cast <ErlRef>(T).Value);
            }
            {
                var     binding = new ErlVarBind();
                ErlList obj     = new ErlList(new ErlLong(10), new ErlDouble(30.0),
                                              new ErlString("abc"), new ErlAtom("a"),
                                              new ErlBinary(new byte[] { 1, 2, 3 }), false, new ErlBoolean(true));
                IErlObject pat = ErlObject.Parse("T");
                Assert.IsTrue(pat.Match(obj, binding));
                IErlObject expected = ErlObject.Parse("[10, 30.0, \"abc\", 'a', ~w, \'false\', true]",
                                                      new ErlBinary(new byte[] { 1, 2, 3 }));
                IErlObject result = binding[T];
                Assert.IsTrue(expected.Equals(result));
            }
        }
示例#7
0
文件: ErlVar.cs 项目: sergey-msu/nfx
 /// <summary>
 /// Perform pattern match on this Erlang term, storing matched variables
 /// found in the pattern into the binding.
 /// </summary>
 public bool Match(IErlObject pattern, ErlVarBind binding)
 {
     if (binding == null)
         return false;
     IErlObject value = binding[Name];
     if (value != null)
         return checkType(value) ? value.Match(pattern, binding) : false;
     if (!checkType(pattern))
         return false;
     IErlObject term = null;
     binding[Name] = pattern.Subst(ref term, binding) ? term : pattern;
     return true;
 }
示例#8
0
        private void process(IQueable msg)
        {
            try
            {
                if (msg is ErlException)
                {
                    this.Mailbox.DeliverError(this, (ErlException)msg);
                    return;
                }
                var erlMsg = msg as ErlMsg;

                if (erlMsg == null)
                {
                    throw new ErlException("Invalid message type: " + msg.GetType());
                }

                var map     = ((ErlDataStore)Store).Map;
                var binding = new ErlVarBind();

                //{Schema, TS, ChangeType :: $d | $w, [{schema, Flds...}]} %% delete, write(upsert)
                //{Schema, TS, ChangeType :: $D | $C | $c, []}             %% Drop, Create, Clear
                if (erlMsg.Msg == null ||
                    !erlMsg.Msg.Match(SUBSCRIPTION_MSG_PATTERN, binding))
                {
                    return;
                }

                var schemaName = ((ErlAtom)binding[SCHEMA]).Value;
                var ts         = binding[TIMESTAMP].ValueAsLong;
                var op         = (char)((ErlByte)binding[TYPE]).Value;
                var rows       = ((ErlList)binding[ROWS]).Value;

                var schema = map.GetCRUDSchemaForName(schemaName);


                m_LastTimeStamp = new DataTimeStamp(ts);

                CRUDSubscriptionEvent.EventType etp;

                switch (op)
                {
                case 'd': etp = CRUDSubscriptionEvent.EventType.RowDelete; break;

                case 'c': etp = CRUDSubscriptionEvent.EventType.TableClear; break;

                case 'D': etp = CRUDSubscriptionEvent.EventType.TableDrop; break;

                case 'C': etp = CRUDSubscriptionEvent.EventType.TableCreate; break;

                default:  etp = CRUDSubscriptionEvent.EventType.RowUpsert; break;
                }

                if (rows.Count > 0)
                {
                    foreach (var rowTuple in rows.Cast <ErlTuple>())
                    {
                        var row  = map.ErlTupleToRow(schemaName, rowTuple, schema);
                        var data = new CRUDSubscriptionEvent(etp, schema, row, new DataTimeStamp(ts));
                        this.Mailbox.Deliver(this, data);
                    }
                }
                else
                { //used to clear data, no rows are fetched
                    var data = new CRUDSubscriptionEvent(etp, schema, null, new DataTimeStamp(ts));
                    this.Mailbox.Deliver(this, data);
                }
            }
            catch (Exception err)
            {
                App.Log.Write(
                    new Log.Message
                {
                    Type      = Log.MessageType.Error,
                    Topic     = CoreConsts.ERLANG_TOPIC,
                    From      = "{0}.process()".Args(GetType().Name),
                    Text      = err.ToMessageWithType(),
                    Exception = err
                }
                    );
            }
        }
示例#9
0
        public void ErlTestMatchVariable()
        {
            var cases = new KeyValueList <string, IErlObject> {
                { "B", new ErlLong(1) },
                { "B", new ErlAtom("abc") },
                { "B", new ErlString("efg") },
                { "B", new ErlDouble(10.0) },
                { "B::int()", new ErlLong(10) },
                { "B::integer()", new ErlLong(20) },
                { "B::string()", new ErlString("xxx") },
                { "B::atom()", new ErlAtom("xyz") },
                { "B::float()", new ErlDouble(5.0) },
                { "B::double()", new ErlDouble(3.0) },
                { "B::binary()", new ErlBinary(new byte[] { 1, 2, 3 }) },
                { "B::bool()", new ErlBoolean(true) },
                { "B::boolean()", new ErlBoolean(false) },
                { "B::byte()", new ErlByte(1) },
                { "B::char()", new ErlByte('a') },
                { "B::list()", new ErlList(1, 2, 3) },
                { "B::tuple()", new ErlTuple(new ErlByte('a'), 1, "aaa") },
                { "B::pid()", new ErlPid("xxx", 1, 2, 3) },
                { "B::ref()", new ErlRef("xxx", 1, 0, 0, 3) },
                { "B::reference()", new ErlRef("xxx", 1, 0, 0, 3) },
                { "B::port()", new ErlPort("xxx", 1, 3) }
            };

            foreach (var p in cases)
            {
                {
                    IErlObject pat = p.Key.ToErlObject();
                    IErlObject obj = p.Value;

                    var binding = new ErlVarBind();
                    binding[B] = obj;

                    Assert.IsTrue(pat.Match(obj, binding));
                }

                {
                    IErlObject pat = p.Key.ToErlObject();
                    IErlObject obj = p.Value;

                    var binding = new ErlVarBind();

                    Assert.IsTrue(pat.Match(obj, binding));

                    var b = binding["B"];

                    Assert.AreEqual(obj.TypeOrder, b.TypeOrder);
                    Assert.IsTrue(obj.Equals(b));
                }
            }

            var revCases = cases.Reverse <KeyValuePair <string, IErlObject> >().ToList();

            cases.Zip(revCases,
                      (p1, p2) => {
                ErlVar pat     = ErlObject.Parse <ErlVar>(p1.Key);
                IErlObject obj = p2.Value;

                var binding = new ErlVarBind();

                if (pat.ValueType == ErlTypeOrder.ErlObject || pat.ValueType == obj.TypeOrder)
                {
                    Assert.IsTrue(pat.Match(obj, binding));
                }
                else
                {
                    Assert.IsFalse(pat.Match(obj, binding));
                }

                return(false);
            }).ToList();
        }
示例#10
0
        //used for subscription
        public int ExecuteWithoutFetch(ICRUDQueryExecutionContext context, Query query)
        {
            var store = ((ErlCRUDQueryExecutionContext)context).DataStore;
            var mbox = ((ErlCRUDQueryExecutionContext)context).ErlMailBox;
            var ts = ((ErlCRUDQueryExecutionContext)context).SubscriptionTimestamp;

            if (!ts.HasValue)
              throw new ErlDataAccessException(StringConsts.ERL_DS_QUERY_TMSTAMP_CTX_ABSENT_ERROR);

            var parsed = prepareQuery(m_Source);

            var reqID = m_Store.NextRequestID;

            var bind = new ErlVarBind();

            var wass = false;
            var wast = false;
            foreach(var erlVar in parsed.ArgVars)
            {
               var name = erlVar.Name.Value;

               if (erlVar.Name==ATOM_Subscriber &&
               erlVar.ValueType==ErlTypeOrder.ErlPid)
               {
             bind.Add(ATOM_Subscriber, mbox.Self);
             wass = true;
             continue;
               }

               if (erlVar.Name==ATOM_Timestamp &&
               erlVar.ValueType==ErlTypeOrder.ErlLong)
               {
             bind.Add(ATOM_Timestamp, new ErlLong(ts.Value.Microseconds));
             wast = true;
             continue;
               }

               var clrPar = query[name];
               if (clrPar==null)
            throw new ErlDataAccessException(StringConsts.ERL_DS_QUERY_PARAM_NOT_FOUND_ERROR.Args(parsed.Source, name));

               bind.Add(erlVar, clrPar.Value);
            }

            if (!wass)
              throw new ErlDataAccessException(StringConsts.ERL_DS_QUERY_SUBSCR_NOT_FOUND_ERROR);
            if (!wast)
              throw new ErlDataAccessException(StringConsts.ERL_DS_QUERY_TMSTAMP_NOT_FOUND_ERROR);

            var request = parsed.ArgTerm.Subst(bind);

            var args = new ErlList
            {
              reqID.ToErlObject(),
              parsed.Module,
              parsed.Function,
              request
            };

            var rawResp = store.ExecuteRPC(ErlDataStore.NFX_CRUD_MOD,
                                       ErlDataStore.NFX_SUBSCRIBE_FUN, args, null);

            var response = rawResp as ErlTuple;

            // {ReqID, {ok, SchemaID, [{row},{row}...]}}
            // {ReqID, {ReqID::int(), {error, Code::int(), Msg}}}

            if (response==null)
              throw new ErlDataAccessException(StringConsts.ERL_DS_INVALID_RESP_PROTOCOL_ERROR+"QryHndlr.Response==null");

            bind = response.Match(EXECUTE_SUBSCRIBE_OK_PATTERN);
            checkForError(EXECUTE_SUBSCRIBE_ERROR_PATTERN, response, bind, reqID);

            //{ReqID::int(), ok}
            return 0;
        }
示例#11
0
        private void checkForError(IErlObject pattern, IErlObject response, ErlVarBind bind, int reqID)
        {
            if (bind != null)
              return;

            bind = response.Match(pattern);
            if (bind == null)
              throw new ErlDataAccessException(StringConsts.ERL_DS_INVALID_RESP_PROTOCOL_ERROR + "invalid error response pattern", new Exception(response.ToString()));

            var gotReqID = bind[ATOM_ReqID].ValueAsLong;

            if (gotReqID != reqID)
              throw new ErlDataAccessException(StringConsts.ERL_DS_INVALID_RESP_PROTOCOL_ERROR + "unexpected transaction ID (expected={0}, got={1})".Args(reqID, gotReqID));

            var ecode = bind[ATOM_Code].ValueAsInt;
            var rmsg  = bind[ATOM_Msg];
            var emsg  = rmsg.TypeOrder == ErlTypeOrder.ErlString || rmsg.TypeOrder == ErlTypeOrder.ErlAtom
                  ? rmsg.ValueAsString
                  : rmsg.ToString();

            Exception error;

            switch (ecode)
            {
              case INVALID_SUBSCRIPTION_REQUEST_EXCEPTION:
            error = new NFX.DataAccess.CRUD.Subscriptions.InvalidSubscriptionRequestException(emsg, null);
            break;
              case -1:
            error = new ErlDataAccessException("Remote error message: {0}".Args(emsg));
            break;
              default:
            error = new ErlDataAccessException("Remote error code {0}. Message: {1}".Args(ecode, emsg));
            break;
            }

            throw error;
        }
示例#12
0
        private void process(IQueable msg)
        {
            try
            {
                if (msg is ErlException)
                {
                    this.Mailbox.DeliverError(this, (ErlException)msg);
                    return;
                }
                var erlMsg = msg as ErlMsg;

                if (erlMsg == null)
                {
                    throw new ErlException("Invalid message type: " + msg.GetType());
                }

                var map     = ((ErlDataStore)Store).Map;
                var binding = new ErlVarBind();

                //{Schema, TS, ChangeType :: $d | $w, [{schema, Flds...}]} %% delete, write(upsert)
                //{Schema, TS, ChangeType :: $D | $C | $c, []}             %% Drop, Create, Clear
                if (erlMsg.Msg == null ||
                    !erlMsg.Msg.Match(SUBSCRIPTION_MSG_PATTERN, binding))
                {
                    return;
                }

                var schemaName = ((ErlAtom)binding[SCHEMA]).Value;
                var ts         = binding[TIMESTAMP].ValueAsLong;
                var op         = (char)((ErlByte)binding[TYPE]).Value;
                var rows       = ((ErlList)binding[ROWS]).Value;

                var schema = map.GetCRUDSchemaForName(schemaName);


                m_LastTimeStamp = new DataTimeStamp(ts);

                CRUDSubscriptionEvent.EventType etp;

                switch (op)
                {
                case 'd': etp = CRUDSubscriptionEvent.EventType.RowDelete; break;

                case 'c': etp = CRUDSubscriptionEvent.EventType.TableClear; break;

                case 'D': etp = CRUDSubscriptionEvent.EventType.TableDrop; break;

                case 'C': etp = CRUDSubscriptionEvent.EventType.TableCreate; break;

                default:  etp = CRUDSubscriptionEvent.EventType.RowUpsert; break;
                }

                if (rows.Count > 0)
                {
                    int errors = 0;
                    foreach (var rowTuple in rows.Cast <ErlTuple>())
                    {
                        try
                        {
                            var row  = map.ErlTupleToRow(schemaName, rowTuple, schema);
                            var data = new CRUDSubscriptionEvent(etp, schema, row, m_LastTimeStamp);
                            this.Mailbox.Deliver(this, data);
                        }
                        catch (Exception ie)
                        {
                            errors++;
                            log(ie);
                        }
                    }

                    // TODO: Add error reporting to user
                }
                else
                { //used to clear data, no rows are fetched
                    var data = new CRUDSubscriptionEvent(etp, schema, null, m_LastTimeStamp);
                    this.Mailbox.Deliver(this, data);
                }
            }
            catch (Exception err)
            {
                log(err);
            }
        }
示例#13
0
    private void process(IQueable msg)
    {
      try
      {
        if (msg is ErlException)
        {
          this.Mailbox.DeliverError(this, (ErlException)msg);
          return;
        }
        var erlMsg  = msg as ErlMsg;

        if (erlMsg == null)
          throw new ErlException("Invalid message type: " + msg.GetType());

        var map     = ((ErlDataStore)Store).Map;
        var binding = new ErlVarBind();

        //{Schema, ChangeType :: $d | $w, [{schema, Flds...}]} %% delete, write(upsert)
        //{Schema, ChangeType :: $D | $C | $c, []}             %% Drop, Create, Clear
        if (erlMsg.Msg==null ||
           !erlMsg.Msg.Match(SUBSCRIPTION_MSG_PATTERN, binding))
          return;

        var schemaName = ((ErlAtom)binding[SCHEMA]).Value;
        var op         = (char)((ErlByte)binding[TYPE]).Value;
        var rows       = ((ErlList)binding[ROWS]).Value;

        var schema = map.GetCRUDSchemaForName(schemaName);

        CRUDSubscriptionEvent.EventType etp;

        switch(op)
        {
          case 'd': etp = CRUDSubscriptionEvent.EventType.RowDelete; break;
          case 'c': etp = CRUDSubscriptionEvent.EventType.TableClear; break;
          case 'D': etp = CRUDSubscriptionEvent.EventType.TableDrop; break;
          case 'C': etp = CRUDSubscriptionEvent.EventType.TableCreate; break;
          default:  etp = CRUDSubscriptionEvent.EventType.RowUpsert; break;
        }

        if (rows.Count>0)
        {
          foreach(var rowTuple in rows.Cast<ErlTuple>())
          {
            var row  = map.ErlTupleToRow(schemaName, rowTuple, schema);
            var data = new CRUDSubscriptionEvent(etp, schema, row);
            this.Mailbox.Deliver(this, data);
          }
        }
        else
        {
          var data = new CRUDSubscriptionEvent(etp, schema, null);
          this.Mailbox.Deliver(this, data);
        }  
      }
      catch(Exception err)
      {
        App.Log.Write(
          new Log.Message
          {
            Type = Log.MessageType.Error,
            Topic = CoreConsts.ERLANG_TOPIC,
            From = "{0}.process()".Args(GetType().Name),
            Text = err.ToMessageWithType(),
            Exception = err 
          }
        );
      }
    }
示例#14
0
        //used for subscription
        public int ExecuteWithoutFetch(ICRUDQueryExecutionContext context, Query query)
        {
            var store = ((ErlCRUDQueryExecutionContext)context).DataStore;
            var mbox  = ((ErlCRUDQueryExecutionContext)context).ErlMailBox;
            var ts    = ((ErlCRUDQueryExecutionContext)context).SubscriptionTimestamp;

            if (!ts.HasValue)
            {
                throw new ErlDataAccessException(StringConsts.ERL_DS_QUERY_TIMESTAMP_CTX_ABSENT_ERROR);
            }

            var parsed = prepareQuery(m_Source);

            var reqID = m_Store.NextRequestID;

            var bind = new ErlVarBind();

            var wass = false;
            var wast = false;

            foreach (var erlVar in parsed.ArgVars)
            {
                var name = erlVar.Name.Value;

                if (erlVar.Name == ATOM_Subscriber &&
                    erlVar.ValueType == ErlTypeOrder.ErlPid)
                {
                    bind.Add(ATOM_Subscriber, mbox.Self);
                    wass = true;
                    continue;
                }

                if (erlVar.Name == ATOM_Timestamp &&
                    erlVar.ValueType == ErlTypeOrder.ErlLong)
                {
                    bind.Add(ATOM_Timestamp, new ErlLong(ts.Value.Microseconds));
                    wast = true;
                    continue;
                }

                var clrPar = query[name];
                if (clrPar == null)
                {
                    throw new ErlDataAccessException(StringConsts.ERL_DS_QUERY_PARAM_NOT_FOUND_ERROR.Args(parsed.Source, name));
                }

                bind.Add(erlVar, clrPar.Value);
            }

            if (!wass)
            {
                throw new ErlDataAccessException(StringConsts.ERL_DS_QUERY_SUBSCRIBER_NOT_FOUND_ERROR);
            }
            if (!wast)
            {
                throw new ErlDataAccessException(StringConsts.ERL_DS_QUERY_TIMESTAMP_NOT_FOUND_ERROR);
            }


            var request = parsed.ArgTerm.Subst(bind);

            var args = new ErlList
            {
                reqID.ToErlObject(),
                parsed.Module,
                parsed.Function,
                request
            };

            var rawResp = store.ExecuteRPC(ErlDataStore.NFX_CRUD_MOD,
                                           ErlDataStore.NFX_SUBSCRIBE_FUN, args, null);

            var response = rawResp as ErlTuple;

            // {ReqID, {ok, SchemaID, [{row},{row}...]}}
            // {ReqID, {ReqID::int(), {error, Code::int(), Msg}}}

            if (response == null)
            {
                throw new ErlDataAccessException(StringConsts.ERL_DS_INVALID_RESPONSE_PROTOCOL_ERROR + "QryHndlr.Response==null");
            }


            bind = response.Match(EXECUTE_SUBSCRIBE_OK_PATTERN);
            if (bind == null)
            {
                bind = response.Match(EXECUTE_SUBSCRIBE_ERROR_PATTERN);
                if (bind == null || bind[ATOM_ReqID].ValueAsLong != reqID)
                {
                    throw new ErlDataAccessException(StringConsts.ERL_DS_INVALID_RESPONSE_PROTOCOL_ERROR + "QryHndlr.Response wrong error");
                }

                var ecode = bind[ATOM_Code].ValueAsInt;
                var emsg  = bind[ATOM_Msg].ToString();

                Exception error = new ErlDataAccessException("Remote error code {0}. Message: '{1}'".Args(ecode, emsg));

                if (ecode == INVALID_SUBSCRIPTION_REQUEST_EXCEPTION)
                {
                    error = new NFX.DataAccess.CRUD.Subscriptions.InvalidSubscriptionRequestException(emsg, error);
                }

                throw error;
            }

            if (bind[ATOM_ReqID].ValueAsLong != reqID)
            {
                throw new ErlDataAccessException(StringConsts.ERL_DS_INVALID_RESPONSE_PROTOCOL_ERROR + "QryHndlr.Response.ReqID mismatch");
            }

            //{ReqID::int(), ok}
            return(0);
        }
示例#15
0
      //used for subscription
      public int ExecuteWithoutFetch(ICRUDQueryExecutionContext context, Query query)
      {
        var store = ((ErlCRUDQueryExecutionContext)context).DataStore;
        var mbox = ((ErlCRUDQueryExecutionContext)context).ErlMailBox;
        var ts = ((ErlCRUDQueryExecutionContext)context).SubscriptionTimestamp;

        if (!ts.HasValue)
          throw new ErlDataAccessException(StringConsts.ERL_DS_QUERY_TIMESTAMP_CTX_ABSENT_ERROR);

        var parsed = prepareQuery(m_Source);

        var reqID = m_Store.NextRequestID;
        
        var bind = new ErlVarBind();

        var wass = false;
        var wast = false;
        foreach(var erlVar in parsed.ArgVars)
        {
           var name = erlVar.Name.Value;

           if (erlVar.Name==ATOM_Subscriber && 
               erlVar.ValueType==ErlTypeOrder.ErlPid)
           {
             bind.Add(ATOM_Subscriber, mbox.Self);
             wass = true;
             continue;
           }

           if (erlVar.Name==ATOM_Timestamp && 
               erlVar.ValueType==ErlTypeOrder.ErlLong)
           {
             bind.Add(ATOM_Timestamp, new ErlLong(ts.Value.Microseconds));
             wast = true;
             continue;
           }

           var clrPar = query[name];
           if (clrPar==null)
            throw new ErlDataAccessException(StringConsts.ERL_DS_QUERY_PARAM_NOT_FOUND_ERROR.Args(parsed.Source, name));

           bind.Add(erlVar, clrPar.Value);
        }

        if (!wass)
          throw new ErlDataAccessException(StringConsts.ERL_DS_QUERY_SUBSCRIBER_NOT_FOUND_ERROR);
        if (!wast)
          throw new ErlDataAccessException(StringConsts.ERL_DS_QUERY_TIMESTAMP_NOT_FOUND_ERROR);


        var request = parsed.ArgTerm.Subst(bind);

        var args = new ErlList
        {
          reqID.ToErlObject(),
          parsed.Module,
          parsed.Function,
          request
        };

        var rawResp = store.ExecuteRPC(ErlDataStore.NFX_CRUD_MOD, 
                                       ErlDataStore.NFX_SUBSCRIBE_FUN, args, null);
                                        
        var response = rawResp as ErlTuple; 

        // {ReqID, {ok, SchemaID, [{row},{row}...]}}
        // {ReqID, {ReqID::int(), {error, Code::int(), Msg}}}

        if (response==null)
          throw new ErlDataAccessException(StringConsts.ERL_DS_INVALID_RESPONSE_PROTOCOL_ERROR+"QryHndlr.Response==null");


        bind = response.Match(EXECUTE_SUBSCRIBE_OK_PATTERN);
        if (bind==null)
        {
          bind = response.Match(EXECUTE_SUBSCRIBE_ERROR_PATTERN);
          if (bind==null || bind[ATOM_ReqID].ValueAsLong != reqID)
            throw new ErlDataAccessException(StringConsts.ERL_DS_INVALID_RESPONSE_PROTOCOL_ERROR+"QryHndlr.Response wrong error");

          var ecode = bind[ATOM_Code].ValueAsInt;
          var emsg  = bind[ATOM_Msg].ToString();

          Exception error = new ErlDataAccessException("Remote error code {0}. Message: '{1}'".Args(ecode, emsg));

          if (ecode==INVALID_SUBSCRIPTION_REQUEST_EXCEPTION)
           error = new NFX.DataAccess.CRUD.Subscriptions.InvalidSubscriptionRequestException(emsg, error);

          throw error;
        }

        if (bind[ATOM_ReqID].ValueAsLong != reqID)
            throw new ErlDataAccessException(StringConsts.ERL_DS_INVALID_RESPONSE_PROTOCOL_ERROR+"QryHndlr.Response.ReqID mismatch");

        //{ReqID::int(), ok}
        return 0;
      }
示例#16
0
        public void ErlVarTest()
        {
            var t = ErlVar.Any;
              Assert.IsFalse(t.Equals(new ErlVar(ConstAtoms.ANY)));
              Assert.AreEqual(ConstAtoms.ANY, t.Name);
              Assert.AreEqual(ErlTypeOrder.ErlObject, t.ValueType);

              t = new ErlVar(N, ErlTypeOrder.ErlLong);
              Assert.AreEqual("N", t.Name.Value);
              Assert.AreEqual(ErlTypeOrder.ErlLong, t.ValueType);

              {
            var bind = new ErlVarBind();
            Assert.IsTrue(t.Match(new ErlByte(10), bind));
            Assert.AreEqual(10, bind["N"].ValueAsLong);
            bind.Clear();
            var q = new ErlVar("N", ErlTypeOrder.ErlByte);
            Assert.IsTrue(q.Match(new ErlLong(111), bind));
            Assert.AreEqual(111, bind["N"].ValueAsLong);
              }

              Assert.IsFalse(t.Matches(new ErlVar()));
              Assert.IsFalse(new ErlVar(A).Matches(new ErlVar(A)));
              Assert.IsFalse(new ErlVar(A).Matches(new ErlVar(B)));
              Assert.AreEqual(new ErlVarBind { { N, (ErlLong)10 } }, t.Match((ErlLong)10));
              Assert.AreEqual(new ErlVarBind { { A, (ErlLong)10 } }, new ErlVar(A).Match((ErlLong)10));

              Assert.AreEqual(-1, new ErlAtom("ok").CompareTo(t));
              Assert.Throws<ErlIncompatibleTypesException>(() => { var x = t.ValueAsObject; });
              Assert.Throws<ErlIncompatibleTypesException>(() => { var x = t.ValueAsInt; });
              Assert.Throws<ErlIncompatibleTypesException>(() => { var x = t.ValueAsLong; });
              Assert.Throws<ErlIncompatibleTypesException>(() => { var x = t.ValueAsDecimal; });
              Assert.Throws<ErlIncompatibleTypesException>(() => { var x = t.ValueAsDateTime; });
              Assert.Throws<ErlIncompatibleTypesException>(() => { var x = t.ValueAsTimeSpan; });
              Assert.Throws<ErlIncompatibleTypesException>(() => { var x = t.ValueAsDouble; });
              Assert.Throws<ErlIncompatibleTypesException>(() => { var x = t.ValueAsString; });
              Assert.Throws<ErlIncompatibleTypesException>(() => { var x = t.ValueAsBool; });
              Assert.Throws<ErlIncompatibleTypesException>(() => { var x = t.ValueAsChar; });
              Assert.Throws<ErlIncompatibleTypesException>(() => { var x = t.ValueAsByteArray; });
              Assert.AreEqual("N::int()", t.ToString());
              Assert.IsTrue(t.IsScalar);
              Assert.AreEqual(ErlTypeOrder.ErlVar, t.TypeOrder);

              IErlObject temp = null;
              Assert.IsFalse(t.Subst(ref temp, new ErlVarBind { { M, new ErlLong(100) } }));
              Assert.IsTrue(t.Subst(ref temp, new ErlVarBind { { N, new ErlLong(100) } }));
              Assert.AreEqual(new ErlLong(100), temp);

              temp = new ErlVar(M, ErlTypeOrder.ErlLong);
              Assert.IsTrue(temp.Subst(ref temp, new ErlVarBind { { M, new ErlLong(100) } }));
              Assert.AreEqual(ErlTypeOrder.ErlVar, t.Visit(ErlTypeOrder.ErlByte, (acc, o) => ((ErlVar)o).TypeOrder));
              Assert.AreEqual(new ErlLong(100), temp);

              temp = new ErlVar(N, ErlTypeOrder.ErlObject);
              Assert.IsTrue(temp.Subst(ref temp, new ErlVarBind { { N, new ErlLong(100) } }));

              // Invalid variable type
              temp = new ErlVar(N, ErlTypeOrder.ErlAtom);
              Assert.Throws<ErlException>(() => temp.Subst(ref temp, new ErlVarBind { { N, new ErlLong(100) } }));
        }
示例#17
0
        public void ErlVarBindTest()
        {
            var bind = new ErlVarBind
            {
                {new ErlVar("A", ErlTypeOrder.ErlLong),    10},
                {new ErlVar("B", ErlTypeOrder.ErlAtom), "abc"},
                { "C", ErlTypeOrder.ErlDouble, 5}
            };

              Assert.AreEqual((IErlObject)(new ErlLong(10)), bind["A"]);
              Assert.AreEqual((IErlObject)(new ErlAtom("abc")), bind["B"]);
              Assert.AreEqual((IErlObject)(new ErlDouble(5.0)), bind["C"]);

              var term = NFX.Erlang.ErlObject.Parse("{ok, {A::int(), [sasha, B::atom(), C::float()]}}");
              var set = term.Visit(new SortedSet<ErlVar>(), (a, o) => { if (o is ErlVar) a.Add((ErlVar)o); return a; });

              IErlObject res = null;
              Assert.IsTrue(term.Subst(ref res, bind));
              Assert.AreEqual("{ok, {10, [sasha, abc, 5.0]}}".ToErlObject(), res);
        }
示例#18
0
        public void ErlByteTest()
        {
            var t = new ErlByte(10);
              Assert.IsTrue(t.Equals(new ErlByte(10)));
              Assert.AreEqual(t, new ErlByte(10));
              Assert.IsTrue(new ErlByte(1).CompareTo(t) < 0);
              Assert.AreEqual(10, t.Value);
              Assert.AreEqual(10, t.ValueAsInt);
              Assert.AreEqual(10, t.ValueAsLong);
              Assert.AreEqual("10", t.ToString());
              Assert.IsTrue(t.IsScalar);
              Assert.AreEqual(ErlTypeOrder.ErlByte, t.TypeOrder);

              Assert.IsTrue(t.Matches(new ErlByte(10)));
              Assert.AreEqual(new ErlVarBind(), t.Match(new ErlByte(10)));

              Assert.DoesNotThrow(() => { var x = t.ValueAsObject; });
              Assert.AreEqual(10, t.ValueAsInt);
              Assert.AreEqual(10, t.ValueAsLong);
              Assert.AreEqual(10, t.ValueAsDecimal);
              Assert.Throws<ErlIncompatibleTypesException>(() => { var x = t.ValueAsDateTime; });
              Assert.Throws<ErlIncompatibleTypesException>(() => { var x = t.ValueAsTimeSpan; });
              Assert.AreEqual(10.0, t.ValueAsDouble);
              Assert.AreEqual("10", t.ValueAsString);
              Assert.AreEqual(true, t.ValueAsBool);
              Assert.AreEqual('\n', t.ValueAsChar);
              Assert.Throws<ErlIncompatibleTypesException>(() => { var x = t.ValueAsByteArray; });

              IErlObject temp = null;
              Assert.IsFalse(t.Subst(ref temp, new ErlVarBind()));
              Assert.AreEqual(10, t.Visit(0, (acc, o) => o.ValueAsInt));

              char n = (char)t; Assert.AreEqual('\n', n);
              byte m = t; Assert.AreEqual(10, m);
              ErlByte b = 10; Assert.AreEqual(10, b.Value);
              ErlByte k = (ErlByte)10; Assert.AreEqual(10, k.Value);
              ErlByte z = (ErlByte)'\n'; Assert.AreEqual(10, k.Value);

              {
            var bind = new ErlVarBind();
            Assert.IsTrue(b.Match(new ErlLong(10), bind));
            Assert.IsTrue(new ErlLong(10).Match(b, bind));
            b = 111;
            Assert.IsTrue(b.Match(new ErlLong(111), bind));
            Assert.IsTrue(new ErlLong(111).Match(b, bind));
              }
        }
示例#19
0
        public void ErlVarTest()
        {
            var t = ErlVar.Any;

            Assert.IsFalse(t.Equals(new ErlVar(ConstAtoms.ANY)));
            Assert.AreEqual(ConstAtoms.ANY, t.Name);
            Assert.AreEqual(ErlTypeOrder.ErlObject, t.ValueType);

            t = new ErlVar(N, ErlTypeOrder.ErlLong);
            Assert.AreEqual("N", t.Name.Value);
            Assert.AreEqual(ErlTypeOrder.ErlLong, t.ValueType);

            {
                var bind = new ErlVarBind();
                Assert.IsTrue(t.Match(new ErlByte(10), bind));
                Assert.AreEqual(10, bind["N"].ValueAsLong);
                bind.Clear();
                var q = new ErlVar("N", ErlTypeOrder.ErlByte);
                Assert.IsTrue(q.Match(new ErlLong(111), bind));
                Assert.AreEqual(111, bind["N"].ValueAsLong);
            }

            Assert.IsFalse(t.Matches(new ErlVar()));
            Assert.IsFalse(new ErlVar(A).Matches(new ErlVar(A)));
            Assert.IsFalse(new ErlVar(A).Matches(new ErlVar(B)));
            Assert.AreEqual(new ErlVarBind {
                { N, (ErlLong)10 }
            }, t.Match((ErlLong)10));
            Assert.AreEqual(new ErlVarBind {
                { A, (ErlLong)10 }
            }, new ErlVar(A).Match((ErlLong)10));

            Assert.AreEqual(-1, new ErlAtom("ok").CompareTo(t));
            Assert.Throws <ErlIncompatibleTypesException>(() => { var x = t.ValueAsObject; });
            Assert.Throws <ErlIncompatibleTypesException>(() => { var x = t.ValueAsInt; });
            Assert.Throws <ErlIncompatibleTypesException>(() => { var x = t.ValueAsLong; });
            Assert.Throws <ErlIncompatibleTypesException>(() => { var x = t.ValueAsDecimal; });
            Assert.Throws <ErlIncompatibleTypesException>(() => { var x = t.ValueAsDateTime; });
            Assert.Throws <ErlIncompatibleTypesException>(() => { var x = t.ValueAsTimeSpan; });
            Assert.Throws <ErlIncompatibleTypesException>(() => { var x = t.ValueAsDouble; });
            Assert.Throws <ErlIncompatibleTypesException>(() => { var x = t.ValueAsString; });
            Assert.Throws <ErlIncompatibleTypesException>(() => { var x = t.ValueAsBool; });
            Assert.Throws <ErlIncompatibleTypesException>(() => { var x = t.ValueAsChar; });
            Assert.Throws <ErlIncompatibleTypesException>(() => { var x = t.ValueAsByteArray; });
            Assert.AreEqual("N::int()", t.ToString());
            Assert.IsTrue(t.IsScalar);
            Assert.AreEqual(ErlTypeOrder.ErlVar, t.TypeOrder);

            IErlObject temp = null;

            Assert.IsFalse(t.Subst(ref temp, new ErlVarBind {
                { M, new ErlLong(100) }
            }));
            Assert.IsTrue(t.Subst(ref temp, new ErlVarBind {
                { N, new ErlLong(100) }
            }));
            Assert.AreEqual(new ErlLong(100), temp);

            temp = new ErlVar(M, ErlTypeOrder.ErlLong);
            Assert.IsTrue(temp.Subst(ref temp, new ErlVarBind {
                { M, new ErlLong(100) }
            }));
            Assert.AreEqual(ErlTypeOrder.ErlVar, t.Visit(ErlTypeOrder.ErlByte, (acc, o) => ((ErlVar)o).TypeOrder));
            Assert.AreEqual(new ErlLong(100), temp);

            temp = new ErlVar(N, ErlTypeOrder.ErlObject);
            Assert.IsTrue(temp.Subst(ref temp, new ErlVarBind {
                { N, new ErlLong(100) }
            }));

            // Invalid variable type
            temp = new ErlVar(N, ErlTypeOrder.ErlAtom);
            Assert.Throws <ErlException>(() => temp.Subst(ref temp, new ErlVarBind {
                { N, new ErlLong(100) }
            }));
        }
示例#20
0
文件: ErlVar.cs 项目: sergey-msu/nfx
 /// <summary>
 /// Perform pattern match on this Erlang term returning null if match fails
 /// or a dictionary of matched variables bound in the pattern
 /// </summary>
 public ErlVarBind Match(IErlObject pattern)
 {
     var binding = new ErlVarBind();
     return Match(pattern, binding) ? binding : null;
 }
        //used for subscription
        public int ExecuteWithoutFetch(ICRUDQueryExecutionContext context, Query query)
        {
            var store = ((ErlCRUDQueryExecutionContext)context).DataStore;
            var mbox  = ((ErlCRUDQueryExecutionContext)context).ErlMailBox;
            var ts    = ((ErlCRUDQueryExecutionContext)context).SubscriptionTimestamp;

            if (!ts.HasValue)
            {
                throw new ErlDataAccessException(StringConsts.ERL_DS_QUERY_TMSTAMP_CTX_ABSENT_ERROR);
            }

            var parsed = prepareQuery(m_Source);

            var reqID = m_Store.NextRequestID;

            var bind = new ErlVarBind();

            var wass = false;
            var wast = false;

            foreach (var erlVar in parsed.ArgVars)
            {
                var name = erlVar.Name.Value;

                if (erlVar.Name == ATOM_Subscriber &&
                    erlVar.ValueType == ErlTypeOrder.ErlPid)
                {
                    bind.Add(ATOM_Subscriber, mbox.Self);
                    wass = true;
                    continue;
                }

                if (erlVar.Name == ATOM_Timestamp &&
                    erlVar.ValueType == ErlTypeOrder.ErlLong)
                {
                    bind.Add(ATOM_Timestamp, new ErlLong(ts.Value.Microseconds));
                    wast = true;
                    continue;
                }

                var clrPar = query[name];
                if (clrPar == null)
                {
                    throw new ErlDataAccessException(StringConsts.ERL_DS_QUERY_PARAM_NOT_FOUND_ERROR.Args(parsed.Source, name));
                }

                bind.Add(erlVar, clrPar.Value);
            }

            if (!wass)
            {
                throw new ErlDataAccessException(StringConsts.ERL_DS_QUERY_SUBSCR_NOT_FOUND_ERROR);
            }
            if (!wast)
            {
                throw new ErlDataAccessException(StringConsts.ERL_DS_QUERY_TMSTAMP_NOT_FOUND_ERROR);
            }


            var request = parsed.ArgTerm.Subst(bind);

            var args = new ErlList
            {
                reqID.ToErlObject(),
                parsed.Module,
                parsed.Function,
                request
            };

            var rawResp = store.ExecuteRPC(ErlDataStore.NFX_CRUD_MOD,
                                           ErlDataStore.NFX_SUBSCRIBE_FUN, args, null);

            var response = rawResp as ErlTuple;

            // {ReqID, {ok, SchemaID, [{row},{row}...]}}
            // {ReqID, {ReqID::int(), {error, Code::int(), Msg}}}

            if (response == null)
            {
                throw new ErlDataAccessException(StringConsts.ERL_DS_INVALID_RESP_PROTOCOL_ERROR + "QryHndlr.Response==null");
            }


            bind = response.Match(EXECUTE_SUBSCRIBE_OK_PATTERN);
            checkForError(EXECUTE_SUBSCRIBE_ERROR_PATTERN, response, bind, reqID);

            //{ReqID::int(), ok}
            return(0);
        }
示例#22
0
    private void process(IQueable msg)
    {
      try
      {
        if (msg is ErlException)
        {
          this.Mailbox.DeliverError(this, (ErlException)msg);
          return;
        }
        var erlMsg  = msg as ErlMsg;

        if (erlMsg == null)
          throw new ErlException("Invalid message type: " + msg.GetType());

        var map     = ((ErlDataStore)Store).Map;
        var binding = new ErlVarBind();

        //{Schema, TS, ChangeType :: $d | $w, [{schema, Flds...}]} %% delete, write(upsert)
        //{Schema, TS, ChangeType :: $D | $C | $c, []}             %% Drop, Create, Clear
        if (erlMsg.Msg==null ||
           !erlMsg.Msg.Match(SUBSCRIPTION_MSG_PATTERN, binding))
          return;

        var schemaName = ((ErlAtom)binding[SCHEMA]).Value;
        var ts         = binding[TIMESTAMP].ValueAsLong;
        var op         = (char)((ErlByte)binding[TYPE]).Value;
        var rows       = ((ErlList)binding[ROWS]).Value;

        var schema = map.GetCRUDSchemaForName(schemaName);


        m_LastTimeStamp = new DataTimeStamp(ts);

        CRUDSubscriptionEvent.EventType etp;

        switch(op)
        {
          case 'd': etp = CRUDSubscriptionEvent.EventType.RowDelete; break;
          case 'c': etp = CRUDSubscriptionEvent.EventType.TableClear; break;
          case 'D': etp = CRUDSubscriptionEvent.EventType.TableDrop; break;
          case 'C': etp = CRUDSubscriptionEvent.EventType.TableCreate; break;
          default:  etp = CRUDSubscriptionEvent.EventType.RowUpsert; break;
        }

        if (rows.Count>0)
        {
          int errors = 0;
          foreach(var rowTuple in rows.Cast<ErlTuple>())
          {
            try
            {
              var row  = map.ErlTupleToRow(schemaName, rowTuple, schema);
              var data = new CRUDSubscriptionEvent(etp, schema, row, new DataTimeStamp(ts));
              this.Mailbox.Deliver(this, data);
            }
            catch(Exception ie)
            {
              errors++;
              log(MessageType.Error, "prcs().forea(rTpl)", ie.ToMessageWithType(), ie);
            }
          }

          // TODO: Add error reporting to user
        }
        else
        {  //used to clear data, no rows are fetched
          var data = new CRUDSubscriptionEvent(etp, schema, null, new DataTimeStamp(ts));
          this.Mailbox.Deliver(this, data);
        }  
      }
      catch(Exception err)
      {
        log(MessageType.Error, "prcs().outcatch{}", err.ToMessageWithType(), err);
      }
    }
示例#23
0
      public RowsetBase Execute(ICRUDQueryExecutionContext context, Query query, bool oneRow = false)
      {
        var store = ((ErlCRUDQueryExecutionContext)context).DataStore;
        var mbox = ((ErlCRUDQueryExecutionContext)context).ErlMailBox;

        var parsed = prepareQuery(m_Source);

        var reqID = m_Store.NextRequestID;
        
        var bind = new ErlVarBind();

        foreach(var erlVar in parsed.ArgVars)
        {
           var name = erlVar.Name.Value;

           var clrPar = query[name];
           if (clrPar==null)
            throw new ErlDataAccessException(StringConsts.ERL_DS_QUERY_PARAM_NOT_FOUND_ERROR.Args(parsed.Source, name));

           bind.Add(erlVar, clrPar.Value);
        }

        var request = parsed.ArgTerm.Subst(bind);

        var args = new ErlList
        {
          reqID.ToErlObject(),
          parsed.Module,
          parsed.Function,
          request
        };

        var rawResp = store.ExecuteRPC(ErlDataStore.NFX_CRUD_MOD, 
                                       ErlDataStore.NFX_RPC_FUN, args, mbox);
                                        
        var response = rawResp as ErlTuple; 

        // {ReqID, {ok, SchemaID, [{row},{row}...]}}
        // {ReqID, {error, Reason}}

        if (response==null)
          throw new ErlDataAccessException(StringConsts.ERL_DS_INVALID_RESPONSE_PROTOCOL_ERROR+"QryHndlr.Response timeout");


        bind = response.Match(EXECUTE_OK_PATTERN);
        if (bind==null)
        {
          bind = response.Match(EXECUTE_ERROR_PATTERN);
          if (bind==null || bind[ATOM_ReqID].ValueAsLong != reqID)
            throw new ErlDataAccessException(StringConsts.ERL_DS_INVALID_RESPONSE_PROTOCOL_ERROR+"QryHndlr.Response wrong error");

          throw new ErlDataAccessException("Remote error code {0}. Message: '{1}'".Args(bind[ATOM_Code], bind[ATOM_Msg]));
        }

        if (bind[ATOM_ReqID].ValueAsLong != reqID)
            throw new ErlDataAccessException(StringConsts.ERL_DS_INVALID_RESPONSE_PROTOCOL_ERROR+"QryHndlr.Response.ReqID mismatch");

        //{ReqID::int(), {ok, SchemaID::atom(), Rows::list()}}

        var schema = bind[ATOM_SchemaID].ValueAsString;
        var rows = bind[ATOM_Rows] as ErlList;

        //{ok, "tca_jaba",
        //[
        //  {tca_jaba, 1234, tav, "User is cool", true},
        //  {tca_jaba, 2344, zap, "Zaplya xochet pit", false}, 
        //  {tca_jaba, 8944, tav, "User is not good", false} 
        //]};
        return m_Store.Map.ErlCRUDResponseToRowset(schema, rows, query.ResultRowType);
      }
        public RowsetBase Execute(ICRUDQueryExecutionContext context, Query query, bool oneRow = false)
        {
            var store = ((ErlCRUDQueryExecutionContext)context).DataStore;
            var mbox  = ((ErlCRUDQueryExecutionContext)context).ErlMailBox;

            var parsed = prepareQuery(m_Source);

            var reqID = m_Store.NextRequestID;

            var bind = new ErlVarBind();

            foreach (var erlVar in parsed.ArgVars)
            {
                var name = erlVar.Name.Value;

                var clrPar = query[name];
                if (clrPar == null)
                {
                    throw new ErlDataAccessException(StringConsts.ERL_DS_QUERY_PARAM_NOT_FOUND_ERROR.Args(parsed.Source, name));
                }

                bind.Add(erlVar, clrPar.Value);
            }

            var request = parsed.ArgTerm.Subst(bind);

            var args = new ErlList
            {
                reqID.ToErlObject(),
                parsed.Module,
                parsed.Function,
                request
            };

            var rawResp = store.ExecuteRPC(ErlDataStore.NFX_CRUD_MOD,
                                           ErlDataStore.NFX_RPC_FUN, args, mbox);

            var response = rawResp as ErlTuple;

            // {ReqID, {ok, SchemaID, [{row},{row}...]}}
            // {ReqID, {error, Reason}}

            if (response == null)
            {
                throw new ErlDataAccessException(StringConsts.ERL_DS_INVALID_RESP_PROTOCOL_ERROR + "QryHndlr.Response timeout");
            }


            bind = response.Match(EXECUTE_OK_PATTERN);
            checkForError(EXECUTE_ERROR_PATTERN, response, bind, reqID);

            if (bind[ATOM_ReqID].ValueAsLong != reqID)
            {
                throw new ErlDataAccessException(StringConsts.ERL_DS_INVALID_RESP_PROTOCOL_ERROR + "QryHndlr.Response.ReqID mismatch");
            }

            //{ReqID::int(), {ok, SchemaID::atom(), Rows::list()}}

            var schema = bind[ATOM_SchemaID].ValueAsString;
            var rows   = bind[ATOM_Rows] as ErlList;

            //{ok, "tca_jaba",
            //[
            //  {tca_jaba, 1234, tav, "User is cool", true},
            //  {tca_jaba, 2344, zap, "Zaplya xochet pit", false},
            //  {tca_jaba, 8944, tav, "User is not good", false}
            //]};
            return(m_Store.Map.ErlCRUDResponseToRowset(schema, rows, query.ResultRowType));
        }
示例#25
0
    /// <summary>
    /// Receive a message and match it against a given pattern
    /// </summary>
    /// <param name="pattern">Pattern to match the message against</param>
    /// <param name="timeoutMsec">Timeout in milliseconds</param>
    /// <returns>Return a tuple containing the received message and variable
    /// binding object. On timeout the first element of the tuple is null.
    /// On unsuccessful match the second element of the tuple is null</returns>
    public Tuple<IErlObject, ErlVarBind> ReceiveMatch(IErlObject pattern, int timeoutMsec = -1)
    {
      var m = Receive(timeoutMsec);
      if (m == null) return Tuple.Create<IErlObject, ErlVarBind>(null, null);

      var binding = new ErlVarBind();
      bool res = m.Match(pattern, binding);
      return Tuple.Create(m, res ? binding : null);
    }
示例#26
0
文件: ErlVar.cs 项目: sergey-msu/nfx
 public bool Subst(ref IErlObject obj, ErlVarBind binding)
 {
     if (IsAny || binding == null || binding.Empty)
         throw new ErlException(StringConsts.ERL_UNBOUND_VARIABLE_ERROR);
     
     IErlObject term = binding[Name];
     if (term == null)
         //throw new ErlException(StringConsts.VARIABLE_NOT_FOUND_ERROR, Name);
         return false;
     if (!checkType(term))
         throw new ErlException(StringConsts.ERL_VARIABLE_INVALID_VALUE_TYPE_ERROR,
             Name, obj.GetType().Name, ValueType);
     obj = term;
     return true;
 }