The TableServer provides the Dht server end point.
Besides providing entry points for dht operations such as Get, Put, and Create; it also contains the logic necessary to transfer keys when there is churn in the system, this is implemented in ConnectionHandler, DepartureHandler, and TransferState.
Inheritance: IRpcHandler
Beispiel #1
0
            /**
             * <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(Brunet.Connections.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;
                        }
                    }
                }
            }
Beispiel #2
0
      /**
      <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(Brunet.Connections.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;
            }
          }
        }
      }