Package net.tomp2p.p2p

Source Code of net.tomp2p.p2p.Peer

/*
* Copyright 2009 Thomas Bocek
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package net.tomp2p.p2p;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;

import net.tomp2p.connection.ChannelCreator;
import net.tomp2p.connection.ConnectionBean;
import net.tomp2p.connection.PeerBean;
import net.tomp2p.connection.PeerConnection;
import net.tomp2p.connection.PeerCreator;
import net.tomp2p.futures.BaseFuture;
import net.tomp2p.futures.BaseFutureAdapter;
import net.tomp2p.futures.FutureChannelCreator;
import net.tomp2p.futures.FutureDone;
import net.tomp2p.futures.FutureLateJoin;
import net.tomp2p.futures.FuturePeerConnection;
import net.tomp2p.p2p.builder.BootstrapBuilder;
import net.tomp2p.p2p.builder.BroadcastBuilder;
import net.tomp2p.p2p.builder.DiscoverBuilder;
import net.tomp2p.p2p.builder.PingBuilder;
import net.tomp2p.p2p.builder.SendDirectBuilder;
import net.tomp2p.p2p.builder.ShutdownBuilder;
import net.tomp2p.peers.Number160;
import net.tomp2p.peers.PeerAddress;
import net.tomp2p.rpc.BroadcastRPC;
import net.tomp2p.rpc.DirectDataRPC;
import net.tomp2p.rpc.NeighborRPC;
import net.tomp2p.rpc.ObjectDataReply;
import net.tomp2p.rpc.PingRPC;
import net.tomp2p.rpc.QuitRPC;
import net.tomp2p.rpc.RawDataReply;

/**
* This is the main class to start DHT operations. This class makes use of the build pattern and for each DHT operation,
* a builder class is returned. The main operations can be initiated with {@link #put(Number160)},
* {@link #get(Number160)}, {@link #add(Number160)}, {@link #addTracker(Number160)}, {@link #getTracker(Number160)},
* {@link #remove(Number160)}, {@link #submit(Number160, Worker)}, {@link #send(Number160)}, {@link #sendDirect()},
* {@link #broadcast(Number160)}. Each of those operations return a builder that offers more options. One of the main
* difference to a "regular" DHT is that TomP2P can store a map (key-values) instead of just values. To distinguish
* those, the keys are termed location key (for finding the right peer in the network), and content key (to store more
* than one value on a peer). For the put builder e.g. the following options can be set:
*
* <ul>
* <li>{@link PutBuilder#setData(Number160, net.tomp2p.storage.Data)} - puts a content key with a value</li>
* <li>{@link PutBuilder#dataMap(Map) - puts multiple content key / values at once</li>
* <li>{@link PutBuilder#setPutIfAbsent() - only puts data if its not already on the peers</li>
* <li>...</li>
* </ul>
*
* Furthermore, TomP2P also provides to store keys in different domains to avoid key collisions
* ({@link PutBuilder#setDomainKey(Number160)).
*
* @author Thomas Bocek
*/
public class Peer {
    // As soon as the user calls listen, this connection handler is set
    private final PeerCreator peerCreator;
    // the id of this node
    private final Number160 peerId;
    // the p2p network identifier, two different networks can have the same
    // ports
    private final int p2pId;

    // Distributed
    private DistributedRouting distributedRouting;

    // RPC
    private PingRPC pingRCP;
    private QuitRPC quitRPC;
    private NeighborRPC neighborRPC;
    private DirectDataRPC directDataRPC;
    private BroadcastRPC broadcastRPC;

    private volatile boolean shutdown = false;
   
    private List<AutomaticFuture> automaticFutures = Collections.synchronizedList(new ArrayList<AutomaticFuture>(1));
    private List<Shutdown> shutdownListeners = Collections.synchronizedList(new ArrayList<Shutdown>(5));

    /**
     * Create a peer. Please use {@link PeerBuilder} to create a class
     *
     * @param p2pID
     *            The P2P ID
     * @param peerId
     *            The Id of the peer
     * @param peerCreator
     *            The peer creator that holds the peer bean and connection bean
     */
    Peer(final int p2pID, final Number160 peerId, final PeerCreator peerCreator) {
        this.p2pId = p2pID;
        this.peerId = peerId;
        this.peerCreator = peerCreator;
    }

    PeerCreator peerCreator() {
        return peerCreator;
    }

    public PingRPC pingRPC() {
        if (pingRCP == null) {
            throw new RuntimeException("Not enabled, please enable this RPC in PeerMaker");
        }
        return pingRCP;
    }

    public Peer pingRPC(PingRPC pingRCP) {
        this.pingRCP = pingRCP;
        return this;
    }
   
    public QuitRPC quitRPC() {
      if (quitRPC == null) {
            throw new RuntimeException("Not enabled, please enable this RPC in PeerMaker");
        }
        return quitRPC;   
    }
   
    public Peer quitRPC(QuitRPC quitRPC) {
      this.quitRPC = quitRPC;
        return this;
    }

    public NeighborRPC neighborRPC() {
        if (neighborRPC == null) {
            throw new RuntimeException("Not enabled, please enable this RPC in PeerMaker");
        }
        return neighborRPC;
    }

    public Peer neighborRPC(NeighborRPC neighborRPC) {
        this.neighborRPC = neighborRPC;
        return this;
    }

    public DirectDataRPC directDataRPC() {
        if (directDataRPC == null) {
            throw new RuntimeException("Not enabled, please enable this RPC in PeerMaker");
        }
        return directDataRPC;
    }

    public Peer directDataRPC(DirectDataRPC directDataRPC) {
        this.directDataRPC = directDataRPC;
        return this;
    }

    public BroadcastRPC broadcastRPC() {
        if (broadcastRPC == null) {
            throw new RuntimeException("Not enabled, please enable this RPC in PeerMaker");
        }
        return broadcastRPC;
    }
   
    public Peer broadcastRPC(BroadcastRPC broadcastRPC) {
        this.broadcastRPC = broadcastRPC;
        return this;
    }

    public DistributedRouting distributedRouting() {
        if (distributedRouting == null) {
            throw new RuntimeException("Not enabled, please enable this P2P function in PeerMaker");
        }
        return distributedRouting;
    }

    public void distributedRouting(DistributedRouting distributedRouting) {
        this.distributedRouting = distributedRouting;
    }

    public PeerBean peerBean() {
        return peerCreator.peerBean();
    }

    public ConnectionBean connectionBean() {
        return peerCreator.connectionBean();
    }

    public Number160 peerID() {
        return peerId;
    }

    public int p2pId() {
        return p2pId;
    }

    public PeerAddress peerAddress() {
        return peerBean().serverPeerAddress();
    }
   
    public Peer notifyAutomaticFutures(BaseFuture future) {
      synchronized (automaticFutures) {
        for(AutomaticFuture automaticFuture:automaticFutures) {
                automaticFuture.futureCreated(future);
        }
        }
        return this;
    }

    // *********************************** Basic P2P operation starts here

    public void rawDataReply(final RawDataReply rawDataReply) {
        directDataRPC().rawDataReply(rawDataReply);
    }

    public void objectDataReply(final ObjectDataReply objectDataReply) {
        directDataRPC().objectDataReply(objectDataReply);
    }
   
    public FuturePeerConnection createPeerConnection(final PeerAddress destination) {
      return createPeerConnection(destination, PeerConnection.HEART_BEAT_MILLIS);
    }

    /**
     * Opens a TCP connection and keeps it open. The user can provide the idle timeout, which means that the connection
     * gets closed after that time of inactivity. If the other peer goes offline or closes the connection (due to
<<<<<<< HEAD
     * inactivity), further requests with this connections reopens the connection. This methods blocks until a
=======
     * inactivity), further requests with this connections reopens the connection. This method blocks until a
>>>>>>> refs/remotes/nico/master
     * connection can be reserved.
     *
     * @param destination
     *            The end-point to connect to
     * @param heartBeatMillis
     *            // TODO update doc
     *            time in milliseconds after a connection gets closed if idle, -1 if it should remain always open until
     *            the user closes the connection manually.
     * @return A class that needs to be passed to those methods that should use the already open connection. If the
     *         connection could not be reserved, maybe due to a shutdown, null is returned.
     */
    public FuturePeerConnection createPeerConnection(final PeerAddress destination, final int heartBeatMillis) {
        final FuturePeerConnection futureDone = new FuturePeerConnection(destination);
        final FutureChannelCreator fcc = connectionBean().reservation().createPermanent(1);
        fcc.addListener(new BaseFutureAdapter<FutureChannelCreator>() {
            @Override
            public void operationComplete(final FutureChannelCreator future) throws Exception {
                if (future.isSuccess()) {
                    final ChannelCreator cc = fcc.channelCreator();
                    final PeerConnection peerConnection = new PeerConnection(destination, cc, heartBeatMillis);
                    futureDone.done(peerConnection);
                } else {
                    futureDone.failed(future);
                }
            }
        });
        return futureDone;
    }

    // -------------------------------------------------- Direct, bootstrap, ping and broadcast  

    public SendDirectBuilder sendDirect(PeerAddress recipientAddress) {
        return new SendDirectBuilder(this, recipientAddress);
    }

    public SendDirectBuilder sendDirect(FuturePeerConnection recipientConnection) {
        return new SendDirectBuilder(this, recipientConnection);
    }
   
    public SendDirectBuilder sendDirect(PeerConnection peerConnection) {
        return new SendDirectBuilder(this, peerConnection);
    }

    public BootstrapBuilder bootstrap() {
        return new BootstrapBuilder(this);
    }
   
    /**
   * Sends a friendly shutdown message to my close neighbors in the DHT.
   *
   * @return A builder for shutdown that runs asynchronous.
   */
    public ShutdownBuilder announceShutdown() {
        return new ShutdownBuilder(this);
    }

    public PingBuilder ping() {
        return new PingBuilder(this);
    }

    public DiscoverBuilder discover() {
        return new DiscoverBuilder(this);
    }

    public BroadcastBuilder broadcast(Number160 messageKey) {
        return new BroadcastBuilder(this, messageKey);
    }

    /**
     * Shuts down everything.
     *
     * @return The future, when shutdown is completed
     */
    public BaseFuture shutdown() {
        //prevent the shutdown from being called twice
        if (!shutdown) {
            shutdown = true;
           
            final List<Shutdown> copy;
            synchronized (shutdownListeners) {
              copy = new ArrayList<Shutdown>(shutdownListeners);
            }
            final FutureLateJoin<BaseFuture> futureLateJoin = new FutureLateJoin<BaseFuture>(shutdownListeners.size() + 1);
            for(Shutdown shutdown:copy) {
              futureLateJoin.add(shutdown.shutdown());
              removeShutdownListener(shutdown);
            }
            futureLateJoin.add(peerCreator.shutdown());
            return futureLateJoin;
        } else {
            return new FutureDone<Void>().failed("already shutting / shut down");
        }
    }

    /**
     * @return True if the peer is about or already has shutdown
     */
    public boolean isShutdown() {
        return shutdown;
    }

  public Peer addShutdownListener(Shutdown shutdown) {
    shutdownListeners.add(shutdown);
    return this;
    }
 
  public Peer removeShutdownListener(Shutdown shutdown) {
    shutdownListeners.remove(shutdown);
    return this;
  }
 
  public Peer addAutomaticFuture(AutomaticFuture automaticFuture) {
    automaticFutures.add(automaticFuture);
    return this;
    }
 
  public Peer removeAutomaticFuture(AutomaticFuture automaticFuture) {
    automaticFutures.remove(automaticFuture);
    return this;
  }

 
}
TOP

Related Classes of net.tomp2p.p2p.Peer

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.