⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 chordimpl.java

📁 Chord package into p2psim
💻 JAVA
📖 第 1 页 / 共 3 页
字号:

		// set nodeID
		this.setID(localID1);

		// establish connection
		this.createHelp();

	}

	/**
	 * Performs all necessary tasks for creating a new Chord ring. Assumes that
	 * localID and localURL are correctly set. Is invoked by the methods
	 * {@link #create()}, {@link #create(URL)}, and {@link #create(URL, ID)}
	 * only.
	 * 
	 * @throws RuntimeException
	 */
	private final void createHelp() {

		this.logger.debug("Help method for creating a new Chord ring invoked.");

		// create local repository for entries
		this.entries = new Entries();

		// create local repository for node references
		if (NUMBER_OF_SUCCESSORS >= 1) {
			this.references = new References(this.getID(), this.getURL(), 
					NUMBER_OF_SUCCESSORS, this.entries);
		} else {
			throw new RuntimeException(
					"NUMBER_OF_SUCCESSORS intialized with wrong value! "
							+ NUMBER_OF_SUCCESSORS);
		}

		// create NodeImpl instance for communication
		this.localNode = new NodeImpl(this, this.getID(), this.localURL,
				this.references, this.entries);

		// create tasks for fixing finger table, checking predecessor and
		// stabilizing
		this.createTasks();

		// accept content requests from outside
		this.localNode.acceptEntries();

	}

	/**
	 * Creates the tasks that must be executed periodically to maintain the
	 * Chord overlay network and schedules them with help of a
	 * {@link ScheduledExecutorService}.
	 */
	private final void createTasks() {

		// start thread which periodically stabilizes with successor
		this.maintenanceTasks.scheduleWithFixedDelay(new StabilizeTask(
				this.localNode, this.references, this.entries),
				ChordImpl.STABILIZE_TASK_START,
				ChordImpl.STABILIZE_TASK_INTERVAL, TimeUnit.SECONDS);

		// start thread which periodically attempts to fix finger table
		this.maintenanceTasks.scheduleWithFixedDelay(new FixFingerTask(
				this.localNode, this.getID(), this.references),
				ChordImpl.FIX_FINGER_TASK_START,
				ChordImpl.FIX_FINGER_TASK_INTERVAL, TimeUnit.SECONDS);

		// start thread which periodically checks whether predecessor has
		// failed
		this.maintenanceTasks.scheduleWithFixedDelay(new CheckPredecessorTask(
				this.references), ChordImpl.CHECK_PREDECESSOR_TASK_START,
				ChordImpl.CHECK_PREDECESSOR_TASK_INTERVAL, TimeUnit.SECONDS);
	}

	public final void join(URL bootstrapURL) throws ServiceException {

		// check if parameters are valid
		if (bootstrapURL == null) {
			throw new NullPointerException(
					"At least one parameter is null which is not permitted!");
		}

		// is node already connected?
		if (this.localNode != null) {
			throw new ServiceException(
					"Cannot join network; node is already connected!");
		}

		// has nodeURL been set?
		if (this.localURL == null) {
			throw new ServiceException("Node URL is not set yet! Please "
					+ "set URL with help of setURL(URL) "
					+ "before invoking join(URL)!");
		}

		// if necessary, generate nodeID out of nodeURL
		if (this.getID() == null) {
			this.setID(this.hashFunction.createUniqueNodeID(this.localURL));
		}

		// establish connection
		this.joinHelp(bootstrapURL);

	}

	public final void join(URL localURL1, URL bootstrapURL)
			throws ServiceException {

		// check if parameters are valid
		if (localURL1 == null || bootstrapURL == null) {
			throw new NullPointerException(
					"At least one parameter is null which is not permitted!");
		}

		// is node already connected?
		if (this.localNode != null) {
			throw new ServiceException(
					"Cannot join network; node is already connected!");
		}

		// set nodeURL
		this.localURL = localURL1;

		// if necessary, generate nodeID out of nodeURL
		if (this.getID() == null) {
			this.setID(this.hashFunction.createUniqueNodeID(this.localURL));
		}

		// establish connection
		this.joinHelp(bootstrapURL);

	}

	public final void join(URL localURL1, ID localID1, URL bootstrapURL)
			throws ServiceException {

		// check if parameters are valid
		if (localURL1 == null || localID1 == null || bootstrapURL == null) {
			throw new NullPointerException(
					"At least one parameter is null which is not permitted!");
		}

		// is node already connected?
		if (this.localNode != null) {
			throw new ServiceException(
					"Cannot join network; node is already connected!");
		}

		// set nodeURL
		this.localURL = localURL1;

		// set nodeID
		this.setID(localID1);

		// establish connection
		this.joinHelp(bootstrapURL);

	}

	/**
	 * Performs all necessary tasks for joining an existing Chord ring. Assumes
	 * that localID and localURL are correctly set. Is invoked by the methods
	 * {@link #join(URL)}, {@link #join(URL, URL)}, and
	 * {@link #join(URL, ID, URL)} only.
	 * 
	 * @param bootstrapURL
	 *            URL of bootstrap node. Must not be null!.
	 * @throws ServiceException
	 *             If anything goes wrong during the join process.
	 * @throws RuntimeException
	 *             Length of successor list has not been initialized correctly.
	 * @throws IllegalArgumentException
	 *             <code>boostrapURL</code> is null!
	 */
	private final void joinHelp(URL bootstrapURL) throws ServiceException {

		// create local repository for entries
		this.entries = new Entries();

		// create local repository for node references
		if (NUMBER_OF_SUCCESSORS >= 1) {
			this.references = new References(this.getID(), this.getURL(), 
					NUMBER_OF_SUCCESSORS, this.entries);
		} else {
			throw new RuntimeException(
					"NUMBER_OF_SUCCESSORS intialized with wrong value! "
							+ NUMBER_OF_SUCCESSORS);
		}

		// create NodeImpl instance for communication
		this.localNode = new NodeImpl(this, this.getID(), this.localURL,
				this.references, this.entries);

		// create proxy for outgoing connection to bootstrap node
		Node bootstrapNode;
		try {
			bootstrapNode = Proxy.createConnection(this.localURL, bootstrapURL);
		} catch (CommunicationException e) {
			throw new ServiceException(
					"An error occured when creating a proxy for outgoing "
							+ "connection to bootstrap node! Join operation"
							+ "failed!", e);

		}

		// only an optimization: store reference on bootstrap node
		this.references.addReference(bootstrapNode);

		// Asking for my successor at node bootstrapNode.nodeID

		// find my successor
		Node mySuccessor;
		try {
			mySuccessor = bootstrapNode.findSuccessor(this.getID());
		} catch (CommunicationException e1) {
			throw new ServiceException("An error occured when trying to find "
					+ "the successor of this node using bootstrap node "
					+ "with url " + bootstrapURL.toString() + "! Join "
					+ "operation failed!", e1);
		}

		// store reference on my successor
		this.logger.info(this.localURL + " has successor "
				+ mySuccessor.getNodeURL());
		this.references.addReference(mySuccessor);

		// notify successor for the first time and copy keys from successor
		RefsAndEntries copyOfRefsAndEntries;
		try {
			copyOfRefsAndEntries = mySuccessor
					.notifyAndCopyEntries(this.localNode);
		} catch (CommunicationException e2) {
			throw new ServiceException("An error occured when contacting "
					+ "the successor of this node in order to "
					+ "obtain its references and entries! Join "
					+ "operation failed!", e2);
		}

		List<Node> refs = copyOfRefsAndEntries.getRefs();
		/*
		 * The first list item is the current predecessor of our successor. Now
		 * we are the predecessor, so we can assume, that it must be our
		 * predecessor. 10.06.2007 sven.
		 */
		boolean predecessorSet = false;
		int count = 0;
		while (!predecessorSet) {
			logger.debug("Size of refs: " + refs.size());
			// there is only one other peer in the network
			if (refs.size() == 1) {
				logger
						.info("Adding successor as predecessor as there are only two peers! "
								+ mySuccessor);
				this.references.addReferenceAsPredecessor(mySuccessor);
				predecessorSet = true;
				logger.debug("Actual predecessor: "
						+ this.references.getPredecessor());
			} else {
				// we got the right predecessor and successor
				if (this.getID().isInInterval(refs.get(0).getNodeID(),
						mySuccessor.getNodeID())) {
					this.references.addReferenceAsPredecessor(refs.get(0));
					predecessorSet = true;
				} else {
					/*
					 * if ID of potential predecessor is greater than ours it
					 * can be our successor...
					 */
					logger.info("Wrong successor found. Going backwards!!!");
					this.references.addReference(refs.get(0));
					try {
						copyOfRefsAndEntries = refs.get(0)
								.notifyAndCopyEntries(this.localNode);
						refs = copyOfRefsAndEntries.getRefs();
					} catch (CommunicationException e) {
						throw new ServiceException(
								"An error occured when contacting "
										+ "the successor of this node in order to "
										+ "obtain its references and entries! Join "
										+ "operation failed!", e);
					}
				}
			}
		}

		// add new references, if pings are successful //removed ping to new
		// references. 17.09.2007 sven
		for (Node newReference : copyOfRefsAndEntries.getRefs()) {
			if (newReference != null && !newReference.equals(this.localNode)
					&& !this.references.containsReference(newReference)) {

				ChordImpl.this.references.addReference(newReference);
				if (ChordImpl.this.logger.isEnabledFor(DEBUG)) {
					ChordImpl.this.logger.debug("Added reference on "
							+ newReference.getNodeID() + " which responded to "
							+ "ping request");
				}

			}
		}

		// add copied entries of successor
		this.entries.addAll(copyOfRefsAndEntries.getEntries());

		// accept content requests from outside
		this.localNode.acceptEntries();

		// create tasks for fixing finger table, checking predecessor and
		// stabilizing
		this.createTasks();
	}

	public final void leave() {

		if (this.localNode == null) {
			// ring has not been created or joined, st. leave has no effect
			return;
		}

		this.maintenanceTasks.shutdownNow();

		try {
			Node successor = this.references.getSuccessor();
			if (successor != null && this.references.getPredecessor() != null) {
				successor.leavesNetwork(this.references.getPredecessor());
			}
		} catch (CommunicationException e) {
			/*
			 * throw new ServiceException( "An unknown error occured when trying
			 * to contact the " + "successor of this node to inform it about " +
			 * "leaving! Leave operation failed!");
			 */

		}

		this.localNode.disconnect();
		this.asyncExecutor.shutdownNow();
		this.localNode = null;

	}

	public final void insert(Key key, Serializable s) {

		// check parameters
		if (key == null || s == null) {
			throw new NullPointerException(
					"Neither parameter may have value null!");

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -