Esempio n. 1
0
    /**
     * 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;
    }
Esempio n. 2
0
 /**
  * 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();
 }
Esempio n. 3
0
    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;
 }
Esempio n. 5
0
 public RestartState(Linker l, TransportAddress ta)
        : this(l, ta, _MAX_RESTARTS) {
 }
Esempio n. 6
0
 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();
      }
    }
Esempio n. 10
0
 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;
    }