/** * Connectors just send and receive ConnectToMessages. They return all responses * to the ConnectionOverlord that initiated the ConnectToMessage * @return true if we have enough responses for this connector, and should * stop listening for more */ virtual public bool HandleCtmResponse(Connector c, ISender return_path, ConnectToMessage resp) { /** * Time to start linking: */ Linker l = new Linker(_node, resp.Target.Address, resp.Target.Transports, resp.ConnectionType, _node.Address.ToString()); _node.TaskQueue.Enqueue( l ); return true; }
/** * This is a method for use with the RpcManager. Remote * nodes can call the "sys:ctm.ConnectTo" method to * reach this method */ public IDictionary ConnectTo(IDictionary ht) { ConnectToMessage ctm_req = new ConnectToMessage(ht); //Console.Error.WriteLine("[{0}.ConnectTo({1})]", _n.Address, ctm_req); NodeInfo target = ctm_req.Target; string contype = ctm_req.ConnectionType; Linker l = new Linker(_n, target.Address, target.Transports, contype, ctm_req.Token); //Here we start the job: _n.TaskQueue.Enqueue( l ); ConnectToMessage resp = GetCtmResponseTo(ctm_req); //Console.Error.WriteLine("[{0}.ConnectTo()->{1}]", _n.Address, resp); return resp.ToDictionary(); }
virtual protected void ConnectTo(Address target, string ConnectionType) { ConnectionType mt = Connection.StringToMainType(ConnectionType); /* * This is an anonymous delegate which is called before * the Connector starts. If it returns true, the Connector * will finish immediately without sending an ConnectToMessage */ Linker l = new Linker(_node, target, null, ConnectionType, _node.Address.ToString()); object link_task = l.Task; Connector.AbortCheck abort = delegate(Connector c) { bool stop = false; stop = _node.ConnectionTable.Contains( mt, target ); if (!stop ) { /* * Make a linker to get the task. We won't use * this linker. * No need in sending a ConnectToMessage if we * already have a linker going. */ stop = _node.TaskQueue.HasTask( link_task ); } return stop; }; if (abort(null)) { return; } ConnectToMessage ctm = new ConnectToMessage(ConnectionType, _node.GetNodeInfo(8), _node.Address.ToString()); ISender send = new AHSender(_node, target, AHPacket.AHOptions.Exact); Connector con = new Connector(_node, send, ctm, this); con.FinishEvent += ConnectorEndHandler; con.AbortIf = abort; _node.TaskQueue.Enqueue(con); }
public LinkProtocolState(Linker l, TransportAddress ta, Edge e) { _linker = l; _node = l.LocalNode; _contype = l.ConType; _target_lock = null; _lm_reply = new WriteOnce<LinkMessage>(); _x = new WriteOnce<Exception>(); _con = new WriteOnce<Connection>(); _ta = ta; _is_finished = 0; //Setup the edge: _e = e; _result = Result.None; }
public RestartState(Linker l, TransportAddress ta) : this(l, ta, _MAX_RESTARTS) { }
public RestartState(Linker l, TransportAddress ta, int remaining_attempts) { _linker = l; _ta = ta; _restart_attempts = remaining_attempts; _first_start = 1; }
public LeafConnectionOverlord(Node local) { _compensate = 0; _local = local; _linker = null; _sync = new object(); _rnd = new Random( _local.GetHashCode() ^ unchecked((int)DateTime.UtcNow.Ticks) ); _default_retry_interval = new TimeSpan(0,0,0,0,10000); _current_retry_interval = new TimeSpan(0,0,0,0,10000); //We initialize at at year 1 to start with: _last_retry = DateTime.MinValue; _last_non_leaf_connection_event = DateTime.MinValue; _last_trim = DateTime.MinValue; /* * When a node is removed from the ConnectionTable, * we should check to see if we need to work to get a * replacement */ lock(_sync) { local.ConnectionTable.DisconnectionEvent += this.CheckAndConnectHandler; local.ConnectionTable.ConnectionEvent += this.CheckAndConnectHandler; /** * Every heartbeat we check to see if we need to act */ local.HeartBeatEvent += this.CheckAndConnectHandler; } }
/** * When a Linker finishes, this method is called. This is * to do memory management of the Linker objects */ protected void LinkerFinishHandler(object linker, EventArgs args) { //We need to remove this linker from our list: lock( _sync ) { _linker = null; } }
/** * Linker objects call this when they are done, and we start * again if we need to */ public void CheckAndConnectHandler(object linker, EventArgs args) { ConnectionEventArgs cea = args as ConnectionEventArgs; DateTime now = DateTime.UtcNow; Linker new_linker = null; lock(_sync) { if( cea != null ) { //This is a connection event. if( cea.Connection.MainType != ConnectionType.Leaf ) { _last_non_leaf_connection_event = now; } } //Check in order of cheapness, so we can avoid hard work... bool time_to_start = (now - _last_retry >= _current_retry_interval ); if ( (_linker == null) && time_to_start && IsActive && NeedConnection ) { //Now we double the retry interval. When we get a connection //We reset it back to the default value: _last_retry = now; _current_retry_interval += _current_retry_interval; _current_retry_interval = (_MAX_RETRY_INTERVAL < _current_retry_interval) ? _MAX_RETRY_INTERVAL : _current_retry_interval; //Get a random address to connect to: //Make a copy: object[] tas = _local.RemoteTAs.ToArray(); /* * Make a randomized list of TransportAddress objects to connect to: * This is a very nice algorithm. It is optimal in that it produces * a permutation of a list using N swaps and log(N!) bits * of entropy. */ for(int j = 0; j < tas.Length; j++) { //Swap the j^th position with this position: int i = _rnd.Next(j, tas.Length); if( i != j ) { object temp_ta = tas[i]; tas[i] = tas[j]; tas[j] = temp_ta; } } /** * Make a Link to a remote node */ _linker = new Linker(_local, null, tas, "leaf", _local.Address.ToString()); new_linker = _linker; } else if (cea != null) { /* * This is the case that there was a non-leaf connection * or disconnection, BUT it is not yet time to start OR * there is current linker running OR we are not active OR * we don't need a connection * * In this case, we set the retry interval back to the default * value. This is because we only do the exponential back * off when there we can't seem to get connected when we try. * Clearly we are getting edges here, so there is no need * for the back-off. */ //Reset the connection interval to the default value: _current_retry_interval = _default_retry_interval; //We are not seeking another connection //log.Info("LeafConnectionOverlord : not seeking connection"); } //Check to see if it is time to trim. }//Drop the lock Trim(); /** * If there is a new linker, start it after we drop the lock */ if( new_linker != null ) { new_linker.FinishEvent += this.LinkerFinishHandler; new_linker.Start(); } }
public RestartState(Linker l, TransportAddress ta, int remaining_attempts) { _linker = l; _ta = ta; _restart_attempts = remaining_attempts; //Compute the interval: Random rand = new Random(); int restart_sec = rand.Next(_MS_RESTART_TIME); _interval = new TimeSpan(0,0,0,0,restart_sec); }
/** * Initiates connection setup. * @param sender the ISender for the Connector to use * @param contype the type of connection we want to make * @param token the token used for connection messages * @param responses the maximum number of ctm response messages to listen */ protected void ConnectTo(ISender sender, string contype, string token, int responses) { ConnectionType mt = Connection.StringToMainType(contype); /* * This is an anonymous delegate which is called before * the Connector starts. If it returns true, the Connector * will finish immediately without sending an ConnectToMessage */ Connector.AbortCheck abort = null; ForwardingSender fs = sender as ForwardingSender; if( fs != null ) { //In general, we only know the exact node we are trying //to reach when we are using a ForwardingSender Address target = fs.Destination; Linker l = new Linker(_node, target, null, contype, token); object linker_task = l.Task; //This is what we check for abort = delegate(Connector c) { bool stop = _node.ConnectionTable.Contains( mt, target ); if (!stop ) { /* * Make a linker to get the task. We won't use * this linker. * No need in sending a ConnectToMessage if we * already have a linker going. */ stop = _node.TaskQueue.HasTask( linker_task ); } return stop; }; if ( abort(null) ) { return; } } //Send the 4 neighbors closest to this node: ArrayList nearest = _node.ConnectionTable.GetNearestTo( (AHAddress)_node.Address, 4); NodeInfo[] near_ni = new NodeInfo[nearest.Count]; int i = 0; foreach(Connection cons in nearest) { //We don't use the TAs, just the addresses near_ni[i] = NodeInfo.CreateInstance(cons.Address); i++; } ConnectToMessage ctm = new ConnectToMessage(contype, _node.GetNodeInfo(8), near_ni, token); Connector con = new Connector(_node, sender, ctm, this); con.AbortIf = abort; //Keep a reference to it does not go out of scope lock( _sync ) { _connectors[con] = responses; } con.FinishEvent += new EventHandler(this.ConnectorEndHandler); //Start up this Task: _node.TaskQueue.Enqueue(con); }
/** * When we get ConnectToMessage responses the connector tells us. */ override public bool HandleCtmResponse(Connector c, ISender ret_path, ConnectToMessage ctm_resp) { /** * Time to start linking: */ Linker l = new Linker(_node, ctm_resp.Target.Address, ctm_resp.Target.Transports, ctm_resp.ConnectionType, ctm_resp.Token); _node.TaskQueue.Enqueue( l ); /** * Check this guys neighbors: */ /* POB: I don't think this is needed because we also do the * same thing in the ConnectorEndHandler, so why do this twice? * In fact, it seems better to wait for all the responses before * looking for the closest one * * commenting this out: * ConnectionList structs = _node.ConnectionTable.GetConnections(ConnectionType.Structured); ConnectToNearer(structs, ctm_resp.Target.Address, ctm_resp.Neighbors); */ //See if we want more: bool got_enough = true; object des_o = _connectors[c]; if( des_o != null ) { got_enough = (c.ReceivedCTMs.Count >= (int)des_o); } return got_enough; }
/** * Connectors just send and receive ConnectToMessages. They return all responses * to the ConnectionOverlord that initiated the ConnectToMessage * @return true if we have enough responses for this connector, and should * stop listening for more */ virtual public bool HandleCtmResponse(Connector c, ISender return_path, ConnectToMessage resp) { /** * Time to start linking: */ ICollection transports = resp.Target.Transports; if(TAAuth != null) { ArrayList trans = new ArrayList(); foreach(TransportAddress ta in resp.Target.Transports) { if(TAAuth.Authorize(ta) != TAAuthorizer.Decision.Deny) { trans.Add(ta); } } transports = trans; } Linker l = new Linker(_node, resp.Target.Address, transports, resp.ConnectionType, resp.Token); l.FinishEvent += LinkerEndHandler; _node.TaskQueue.Enqueue( l ); return true; }