/**
     * 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();
    }
Example #2
0
 /**
  * When the ConnectionTable changes, our cached routes are all trash
  */
 protected void ConnectionTableChangeHandler(object o, System.EventArgs args) {
   Connection new_left = null;
   bool structs_changed = false;
   if( args != null ) {
     /*
      * This is sometimes called (in Route) with args set to null
      * when we need to clear the _route_cache.
      * So don't look at args if they are null.
      */
     ConnectionEventArgs ce = (ConnectionEventArgs)args;
     ConnectionList cl = ce.CList;
     structs_changed = (cl.MainType == ConnectionType.Structured);
     if( structs_changed ) {
       if (cl.Count > 0) {
         /*
          * Compute our left neighbor.  We only need to do this when it
          * has changed.
          */
         int our_idx = cl.IndexOf(_local);
         if( our_idx < 0 ) {
           our_idx = ~our_idx;
         }
         else {
           Console.Error.WriteLine(
             "ERROR: we are in the ConnectionTable: {0}", _local);
         }
         new_left = cl[our_idx];
       }
       else {
         //We have no neighbors:
         new_left = null;
       }
     }
   }
   lock( _sync ) {
     _route_cache.Clear();
     if( structs_changed ) {
       _our_left_n = new_left;
     }
   }
 }
Example #3
0
    protected void StatusChangedHandler(object ct, System.EventArgs args) {
      ConnectionEventArgs ce = (ConnectionEventArgs)args;
      Connection new_con = ce.Connection;
      lock( _sync ) {
        if (_our_left_n != null) {
	        if( new_con.Edge == _our_left_n.Edge ) {
	          _our_left_n = new_con;
	        }
        }
      }
    }
    /**
     * 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);
      }
    }
Example #5
0
 public CachedRoute(Connection route, bool send_local) {
   Route = route;
   DeliverLocally = send_local;
 }
 public ConnectionEventArgs(Connection c, int idx, ConnectionList cl, int view) {
   Connection = c;
   Index = idx;
   CList = cl;
   View = view;
 }
 /**
  * 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;
     RpcManager rpc = RpcManager.GetInstance(this);
     rpc.Invoke(c.Edge, stat_res, "sys:link.GetStatus", req.ToDictionary() );
   }
 }
Example #8
0
 public AnnealingRouting(AHAddress local, ConnectionList structured_cons) {
   //Fake connection to ourselves:
   _local_con = new Connection(null, local, "structured.self", null, null);
   int local_idx;
   _structs = ConnectionList.InsertInto(structured_cons, _local_con, out local_idx);
 }
Example #9
0
 public GreedyRouting(AHAddress local, ConnectionList structured_cons) {
   //Fake connection to ourselves:
   _local_con = new Connection(null, local, "structured.self", null, null);
   int local_idx;
   _structs = ConnectionList.InsertInto(structured_cons, _local_con, out local_idx);
   _NO_ONE = new Pair<Connection, bool>(null, false);
   _LOCAL = new Pair<Connection, bool>(null, true);
 }
      /**
      <summary>Begins a new transfer state to the neighbor connected via con.
      </summary>
      <param name="con">The connection to the neigbhor we will be transferring
      data to.</param>
      <param name="ts">The table server we're providing the transfer for.  C#
      does not allow sub-class objects to have access to their parent objects
      member variables, so we pass it in like this.</param>
      <remarks>
      Step 1:

      Get all the keys between me and my new neighbor.

      Step 2:

      Get all values for those keys, we copy so that we don't worry about
      changes to the dht during this interaction.  This is only a pointer
      copy and since we let the OS deal with removing the contents of an
      entry, we don't need to make copies of the actual entry.

      Step 3:

      Generate another list of keys of up to max parallel transfers and begin
      transferring, that way we do not need to lock access to the entry
      enumerator until non-constructor puts.

      Step 4:

      End constructor, results from puts, cause the next entry to be sent.
      */
      public TransferState(Connection con, TableServer ts) {
        this._ts = ts;
        this._con = con;
        // Get all keys between me and my new neighbor
        LinkedList<MemBlock> keys;
        lock(_ts._sync) {
          keys = _ts._data.GetKeysBetween((AHAddress) _ts._node.Address,
                                      (AHAddress) _con.Address);
        }
        if(Dht.DhtLog.Enabled) {
          ProtocolLog.Write(Dht.DhtLog, String.Format(
                            "Starting transfer from {0} to {1}", 
                            _ts._node.Address, _con.Address));
        }
        int total_entries = 0;
        /* Get all values for those keys, we copy so that we don't worry about
         * changes to the dht during this interaction.  This is only a pointer
         * copy and since we let the OS deal with removing the contents of an
         * entry, we don't need to make copies of the actual entry.
         */
        foreach(MemBlock key in keys) {
          Entry[] entries;
          lock(_ts._sync) {
            LinkedList<Entry> llentries = _ts._data.GetEntries(key);
            if(llentries == null) {
              continue;
            }
            entries = new Entry[llentries.Count];
            total_entries += llentries.Count;
            llentries.CopyTo(entries, 0);
          }
          key_entries.AddLast(entries);
        }
        if(Dht.DhtLog.Enabled) {
          ProtocolLog.Write(Dht.DhtLog, String.Format(
                            "Total keys: {0}, total entries: {1}.", 
                            key_entries.Count, total_entries));
        }
        _entry_enumerator = GetEntryEnumerator();

        /* Here we generate another list of keys that we would like to 
         * this is done here, so that we can lock up the _entry_enumerator
         * only during this stage and not during the RpcManager.Invoke
         */
        LinkedList<Entry> local_entries = new LinkedList<Entry>();
        for(int i = 0; i < MAX_PARALLEL_TRANSFERS && _entry_enumerator.MoveNext(); i++) {
          local_entries.AddLast((Entry) _entry_enumerator.Current);
        }

        foreach(Entry ent in local_entries) {
          Channel queue = new Channel();
          queue.CloseAfterEnqueue();
          queue.CloseEvent += this.NextTransfer;
          int ttl = (int) (ent.EndTime - DateTime.UtcNow).TotalSeconds;
          try {
            _ts._rpc.Invoke(_con.Edge, queue, "dht.PutHandler", ent.Key, ent.Value, ttl, false);
          }
          catch {
            if(_con.Edge.IsClosed) {
              _interrupted = true;
              Done();
              break;
            }
          }
        }
      }