/** * Prefered constructor for a Connection */ public Connection(Edge e, Address a, string connectiontype, StatusMessage sm, LinkMessage peerlm) { Address = a; ConType = String.Intern(connectiontype); CreationTime = DateTime.UtcNow; MainType = StringToMainType(ConType); //Mutable state: var cs = new ConnectionState(e, sm, peerlm, false); _state = new Mutable<ConnectionState>(cs); }
/** * Prefered constructor for a Connection */ public Connection(Edge e, Address a, string connectiontype, StatusMessage sm, LinkMessage peerlm) { _e = e; _a = a; _ct = String.Intern(connectiontype); _stat = sm; _lm = peerlm; _creation_time = DateTime.UtcNow; MainType = StringToMainType(_ct); _as_dict = new WriteOnce<ListDictionary>(); _sub_type = new WriteOnce<string>(); }
/** * Get a StatusMessage for this node */ public IDictionary GetStatus(IDictionary status_message, ISender edge) { //we just got s status request if( 1 == _disconnecting ) { throw new AdrException((int)ErrorMessage.ErrorCode.Disconnecting, "disconnecting"); } StatusMessage sm = new StatusMessage(status_message); Edge from = GetEdge(edge); if(ProtocolLog.LinkDebug.Enabled) { ProtocolLog.Write(ProtocolLog.LinkDebug, String.Format( "{0} -start- sys:link.GetStatus({1},{2})", _node.Address, sm, edge)); } CphState cphstate = null; if(from != null) { cphstate = _edge_to_cphstate[from] as CphState; } /** * StatusMessage objects are used to verify the completion * of the Link protocol. If we receive a StatusMessage request * after we send a LinkMessage response, we know the other * Node got our LinkMessage response, and the connection * is active */ StatusMessage response = null; ConnectionTable tab = _node.ConnectionTable; if (cphstate != null) { try { LinkMessage lm_to_add = cphstate.LM; //This is part of connection process: response = _node.GetStatus( sm.NeighborType, lm_to_add.Local.Address ); Connection con = new Connection(from, lm_to_add.Local.Address, lm_to_add.ConTypeString, sm, lm_to_add); tab.Add(con); } finally { from.CloseEvent -= this.CloseHandler; CloseHandler(from, null); } } else { //This is just a "regular" status request //update our table: Address fadd = null; Connection c = tab.GetConnection(from); if( c != null ) { fadd = c.Address; tab.UpdateStatus(c, sm); } response = _node.GetStatus( sm.NeighborType, fadd ); } if(ProtocolLog.LinkDebug.Enabled) { ProtocolLog.Write(ProtocolLog.LinkDebug, String.Format( "{0} -end- sys:link.GetStatus()->{1}", _node.Address,response)); } return response.ToDictionary(); }
public void SMTest() { Address a = new DirectionalAddress(DirectionalAddress.Direction.Left); TransportAddress ta = TransportAddressFactory.CreateInstance("brunet.tcp://127.0.0.1:5000"); NodeInfo ni = NodeInfo.CreateInstance(a, ta); //Test with one neighbor: ArrayList neighbors = new ArrayList(); neighbors.Add(ni); StatusMessage sm1 = new StatusMessage(ConnectionType.Structured, neighbors); RoundTripHT(sm1); //Console.Error.WriteLine("\n{0}\n", sm1); //Test with many neighbors: for(int i = 5001; i < 5010; i++) { neighbors.Add(NodeInfo.CreateInstance(a, TransportAddressFactory.CreateInstance("brunet.tcp://127.0.0.1:" + i.ToString()))); } StatusMessage sm2 = new StatusMessage(ConnectionType.Unstructured, neighbors); RoundTripHT(sm2); //Console.Error.WriteLine("\n{0}\n", sm2); //Here is a StatusMessage with no neighbors (that has to be a possibility) StatusMessage sm3 = new StatusMessage("structured", new ArrayList()); RoundTripHT(sm3); //Console.Error.WriteLine("\n{0}\n", sm3); }
public void RoundTripHT(StatusMessage sm) { StatusMessage sm2 = new StatusMessage( sm.ToDictionary() ); Assert.AreEqual(sm, sm2, "Hashtable RT"); }
/** * Call the GetStatus method on the given connection */ protected void CallGetStatus(string type, Connection c) { ConnectionTable tab = this.ConnectionTable; if( c != null ) { StatusMessage req = GetStatus(type, c.Address); Channel stat_res = new Channel(1); EventHandler handle_result = delegate(object q, EventArgs eargs) { try { RpcResult r = (RpcResult)stat_res.Dequeue(); StatusMessage sm = new StatusMessage( (IDictionary)r.Result ); tab.UpdateStatus(c, sm); } catch(Exception) { //Looks like lc disappeared before we could update it } }; stat_res.CloseEvent += handle_result; _rpc.Invoke(c.Edge, stat_res, "sys:link.GetStatus", req.ToDictionary() ); } }
public ConnectionState(Edge e, StatusMessage sm, LinkMessage lm, bool discon) { Edge = e; PeerLinkMessage = lm; StatusMessage = sm; Disconnected = discon; }
/** * When we're here, we have the status message */ protected void StatusCloseHandler(object q, EventArgs args) { try { Channel resq = (Channel)q; //If we got no result RpcResult res = (RpcResult)resq.Dequeue(); StatusMessage sm = new StatusMessage((IDictionary)res.Result); if(_node.EdgeVerifyMethod != null) { if(!_node.EdgeVerifyMethod(_node, _e, LinkMessageReply.Local.Address)) { throw new Exception("Edge verification failed!"); } } Connection c = new Connection(_e, LinkMessageReply.Local.Address, _contype, sm, LinkMessageReply); _node.ConnectionTable.Add(c); _con.Value = c; Finish(Result.Success); } catch(InvalidOperationException) { /* * This is unexpected. */ string message = String.Format( "No StatusMessage returned from open({1}) Edge: {0}", _e, !_e.IsClosed); if(ProtocolLog.LinkDebug.Enabled) { ProtocolLog.Write(ProtocolLog.LinkDebug, message); } /* * We got a link message from this guy, but not a status response, * so let's try this TA again. */ Finish(Result.RetryThisTA); } catch(Exception x) { /* * Clearly we got some response from this edge, but something * unexpected happened. Let's try it this edge again if we * can */ if(ProtocolLog.LinkDebug.Enabled) { ProtocolLog.Write(ProtocolLog.LinkDebug, String.Format( "LPS.StatusResultHandler Exception: {0}", x)); } Finish(Result.RetryThisTA); } }
/** return the old state, and new state */ public Pair<ConnectionState,ConnectionState> SetStatus(StatusMessage sm) { var res = _state.Update(delegate(ConnectionState old_state) { if( old_state.Disconnected ) { throw new Exception(String.Format("Connection: {0} is disconnected",this)); } var new_state = new ConnectionState(old_state.Edge, sm, old_state.PeerLinkMessage, false); return new_state; }); var ev = StateChangeEvent; if( null != ev ) { ev(this, res); } return res; }
/** * When we get a response to the sys:link method, this handled * is called */ protected void LinkCloseHandler(object q, EventArgs args) { try { Channel resq = (Channel)q; //If the Channel is empty this will throw an exception: RpcResult res = (RpcResult)resq.Dequeue(); /* Here's the LinkMessage response */ LinkMessage lm = new LinkMessage((IDictionary)res.Result); /** * This will set our LinkMessageReply variable. It can * only be set once, so all future sets will fail. It * will also make sure we have the lock on the target. * If we don't, that will throw an exception */ SetAndCheckLinkReply(lm); //If we got here, we have our response and the Lock on _target_address StatusMessage sm = _node.GetStatus(_contype, lm.Local.Address); /* Make the call */ Channel results = new Channel(); results.CloseAfterEnqueue(); results.CloseEvent += this.StatusCloseHandler; RpcManager rpc = _node.Rpc; if (ProtocolLog.LinkDebug.Enabled) { ProtocolLog.Write(ProtocolLog.LinkDebug, String.Format( "LPS target: {0} Invoking GetStatus() over edge: {1}", _linker.Target, _e)); } /* * This could throw an exception if the Edge is closed */ rpc.Invoke(_e, results, "sys:link.GetStatus", sm.ToDictionary()); } catch (AdrException x) { /* * This happens when the RPC call has some kind of issue, * first we check for common error conditions: */ _x.Value = x; Finish(GetResultForErrorCode(x.Code)); } catch (ConnectionExistsException x) { /* We already have a connection */ _x.Value = x; Finish(Result.ProtocolError); } catch (CTLockException x) { //This is thrown when ConnectionTable cannot lock. Lets try again: _x.Value = x; Finish(Result.RetryThisTA); } catch (LinkException x) { _x.Value = x; if (x.IsCritical) { Finish(Result.MoveToNextTA); } else { Finish(Result.RetryThisTA); } } catch (InvalidOperationException) { //The queue never got anything Finish(Result.MoveToNextTA); } catch (EdgeException) { //The Edge is goofy, let's move on: Finish(Result.MoveToNextTA); } catch (Exception x) { //The protocol was not followed correctly by the other node, fail _x.Value = x; Finish(Result.RetryThisTA); } }
public void RoundTripHT(StatusMessage sm) { StatusMessage sm2 = new StatusMessage(sm.ToDictionary()); Assert.AreEqual(sm, sm2, "Hashtable RT"); }
/** * Get a StatusMessage for this node */ public IDictionary GetStatus(IDictionary status_message, ISender edge) { //we just got s status request if (1 == _disconnecting) { throw new AdrException((int)ErrorMessage.ErrorCode.Disconnecting, "disconnecting"); } StatusMessage sm = new StatusMessage(status_message); Edge from = GetEdge(edge); if (ProtocolLog.LinkDebug.Enabled) { ProtocolLog.Write(ProtocolLog.LinkDebug, String.Format( "{0} -start- sys:link.GetStatus({1},{2})", _node.Address, sm, from)); } CphState cphstate = null; if (from != null) { cphstate = _edge_to_cphstate[from] as CphState; } /** * StatusMessage objects are used to verify the completion * of the Link protocol. If we receive a StatusMessage request * after we send a LinkMessage response, we know the other * Node got our LinkMessage response, and the connection * is active */ StatusMessage response = null; ConnectionTable tab = _node.ConnectionTable; if (cphstate != null) { try { LinkMessage lm_to_add = cphstate.LM; //This is part of connection process: response = _node.GetStatus(sm.NeighborType, lm_to_add.Local.Address); Connection con = new Connection(from, lm_to_add.Local.Address, lm_to_add.ConTypeString, sm, lm_to_add); tab.Add(con); } finally { from.CloseEvent -= this.CloseHandler; CloseHandler(from, null); } } else { //This is just a "regular" status request //update our table: Address fadd = null; Connection c = tab.GetConnection(from); if (c != null) { fadd = c.Address; c.SetStatus(sm); } response = _node.GetStatus(sm.NeighborType, fadd); } if (ProtocolLog.LinkDebug.Enabled) { ProtocolLog.Write(ProtocolLog.LinkDebug, String.Format( "{0} -end- sys:link.GetStatus()->{1}", _node.Address, response)); } return(response.ToDictionary()); }
/** * Prefered constructor for a Connection */ public Connection(Edge e, Address a, string connectiontype, StatusMessage sm, LinkMessage peerlm) { if( null == a ) { throw new System.ArgumentNullException( String.Format("Address cannot be null in Connection: Edge: {0} contype: {1}", e, connectiontype)); } Address = a; ConType = String.Intern(connectiontype); CreationTime = DateTime.UtcNow; MainType = StringToMainType(ConType); //Mutable state: var cs = new ConnectionState(e, sm, peerlm, false); _state = new Mutable<ConnectionState>(cs); }
/** return the old state, and new state */ public Pair<ConnectionState,ConnectionState> SetStatus(StatusMessage sm) { var res = _state.Update(delegate(ConnectionState old_state) { if( old_state.Disconnected ) { throw new Exception(String.Format("Connection: {0} is disconnected",this)); } var new_state = new ConnectionState(old_state.Edge, sm, old_state.PeerLinkMessage, false); return new_state; }); ProtocolLog.WriteIf(ProtocolLog.Connections, String.Format( "SetStatus called on {0}, old status: {1}, new status: {2}", this, res.First.StatusMessage, sm)); var ev = StateChangeEvent; if( null != ev ) { ev(this, res); } return res; }