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); }
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 } ); } }
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)); } }
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; }
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)); } }
/// <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; }
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 } ); } }
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(); }
//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; }
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; }
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); } }
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 } ); } }
//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); }
//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; }
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) } })); }
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); }
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)); } }
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) } })); }
/// <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); }
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); } }
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)); }
/// <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); }
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; }