예제 #1
0
파일: Connection.cs 프로젝트: hseom/brunet
    /**
     * 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);
    }
예제 #2
0
    /**
     * 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>();
    }
예제 #3
0
    /**
     * 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();
    }
예제 #4
0
    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);

    }
예제 #5
0
 public void RoundTripHT(StatusMessage sm) {
  StatusMessage sm2 = new StatusMessage( sm.ToDictionary() );
  Assert.AreEqual(sm, sm2, "Hashtable RT");
 }
예제 #6
0
 /**
  * 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() );
   }
 }
예제 #7
0
파일: Connection.cs 프로젝트: hseom/brunet
 public ConnectionState(Edge e, StatusMessage sm, LinkMessage lm, bool discon) {
   Edge = e;
   PeerLinkMessage = lm;
   StatusMessage = sm;
   Disconnected = discon;
 }
예제 #8
0
    /**
     * 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);
      }
    }
예제 #9
0
파일: Connection.cs 프로젝트: hseom/brunet
 /** 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;
 }
예제 #10
0
        /**
         * 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);
            }
        }
예제 #11
0
        public void RoundTripHT(StatusMessage sm)
        {
            StatusMessage sm2 = new StatusMessage(sm.ToDictionary());

            Assert.AreEqual(sm, sm2, "Hashtable RT");
        }
예제 #12
0
        /**
         * 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());
        }
예제 #13
0
    /**
     * 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);
    }
예제 #14
0
 /** 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;
 }