/** * 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; if(_n.Address.Equals(target.Address)) { throw new Exception("Trying to connect to myself!"); } 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(); }
/// <summary>If we get here, the Linker has completed, we are either /// connected or need to reattempt the connection.</summary> override protected void LinkerEndHandler(object o, EventArgs eargs) { if (!IsActive) { return; } Linker linker = o as Linker; Address addr = linker.Target; Connection con = _node.ConnectionTable.GetConnection(MainType, addr); if (con == null) { FailedConnectionAttempt(addr); } else { ObtainedConnection(con); } }
/** * 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; if (_n.Address.Equals(target.Address)) { throw new Exception("Trying to connect to myself!"); } 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()); }
/** * This method allows a user to add some state in the ConnectTo call (see SNCO). */ virtual protected Connector GetConnector(ISender sender, Address target, string ConnectionType, string token) { 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); }; ConnectToMessage ctm = GetConnectToMessage(ConnectionType, token); Connector con = new Connector(_node, sender, ctm, this, target); con.FinishEvent += ConnectorEndHandler; con.AbortIf = abort; return(con); }
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 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; }
/** * 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 = (new List<TransportAddress>(_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 LeafConnectionOverlord(Node local) { _compensate = 0; _local = local; _linker = null; _sync = new object(); #if BRUNET_SIMULATOR _rnd = Node.SimulatorRandom; #else _rnd = new Random( _local.GetHashCode() ^ unchecked((int)DateTime.UtcNow.Ticks) ); #endif _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; } }
/// <summary>Make sure there are no entries in the Dht, who we should be /// connected to, but aren't.</summary> protected void CheckAndUpdateRemoteTAs(List<TransportAddress> tas) { AHAddress right = null, left = null; BigInteger right_dist = null, left_dist = null; AHAddress addr = _node.Address as AHAddress; // Find the closest left and right nodes foreach(TransportAddress ta in tas) { AHAddress target = (ta as SubringTransportAddress).Target; if(target.Equals(addr)) { continue; } BigInteger ldist = addr.LeftDistanceTo(target); BigInteger rdist = addr.RightDistanceTo(target); if(left_dist == null || ldist < left_dist) { left_dist = ldist; left = target; } if(right_dist == null || rdist < right_dist) { right_dist = rdist; right = target; } } ConnectionList cl = _node.ConnectionTable.GetConnections(ConnectionType.Structured); int local_idx = ~cl.IndexOf(_node.Address); if(left != null) { int remote_idx = ~cl.IndexOf(left); // If we're not connected to the left closest and its closer than any // of our current peers, let's connect to it if(remote_idx > 0 && Math.Abs(local_idx - remote_idx) < 2) { List<TransportAddress> tmp_tas = new List<TransportAddress>(1); tmp_tas.Add(new SubringTransportAddress(left, _shared_namespace)); Linker linker = new Linker(_node, null, tmp_tas, "leaf", addr.ToString()); linker.Start(); } } if(right != null && right != left) { int remote_idx = ~cl.IndexOf(right); // If we're not connected to the right closest and its closer than any // of our current peers, let's connect to it if(remote_idx > 0 && Math.Abs(local_idx - remote_idx) < 2) { List<TransportAddress> tmp_tas = new List<TransportAddress>(1); tas.Add(new SubringTransportAddress(right, _shared_namespace)); Linker linker = new Linker(_node, null, tmp_tas, "leaf", addr.ToString()); linker.Start(); } } UpdateRemoteTAs(tas); }