📄 references.java
字号:
/***************************************************************************
* *
* References.java *
* ------------------- *
* date : 16.08.2004 *
* copyright : (C) 2004/2005 Distributed and *
* Mobile Systems Group *
* Lehrstuhl fuer Praktische Informatik *
* Universitaet Bamberg *
* http://www.lspi.wiai.uni-bamberg.de/ *
* email : sven.kaffille@wiai.uni-bamberg.de *
* karsten.loesing@wiai.uni-bamberg.de *
* *
* *
***************************************************************************/
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* A copy of the license can be found in the license.txt file supplied *
* with this software or at: http://www.gnu.org/copyleft/gpl.html *
* *
***************************************************************************/
package de.uniba.wiai.lspi.chord.service.impl;
import java.util.List;
import de.uniba.wiai.lspi.chord.com.Node;
import de.uniba.wiai.lspi.chord.com.Proxy;
import de.uniba.wiai.lspi.chord.data.ID;
import de.uniba.wiai.lspi.util.logging.Logger;
/**
* Stores all remote references of nodes the local node is connected to and
* provides methods for querying and manipulating these references. Makes use of
* one finger table, one successor list, and one predecessor reference.
*
* @author Karsten Loesing
* @version 1.0.1
*/
final class References {
/**
* Object logger.
*/
private Logger logger;
/**
* This node's finger table.
*/
private FingerTable fingerTable = null;
/**
* This node's successor list
*/
private SuccessorList successorList = null;
/**
* This node's predecessor.
*/
private Node predecessor = null;
/**
* This node's local ID.
*/
private ID localID = null;
/**
* Creates an References object which contains no references.
*
* @param localID
* ID of local node.
* @param numberOfEntriesInSuccessorList
* Length of successor list to be created.
* @param entries
* Reference on this nodes' entries which is passed to creation
* of the successor list.
* @throws NullPointerException
* If either of the parameters is <code>null</code>.
* @throws IllegalArgumentException
* If number of entries in successor list is negative.
*/
References(ID localID, int numberOfEntriesInSuccessorList, Entries entries) {
if (localID == null || entries == null) {
throw new NullPointerException(
"Neither parameter of constructor may be null!");
}
if (numberOfEntriesInSuccessorList < 0)
throw new IllegalArgumentException(
"Number of entries in successor list cannot be negative!");
this.logger = Logger.getLogger(References.class.getName() + "."
+ localID);
this.logger.debug("Logger initialized.");
// store node id
this.localID = localID;
// create empty finger table and successor list
this.fingerTable = new FingerTable(localID, this);
this.successorList = new SuccessorList(localID,
numberOfEntriesInSuccessorList, this, entries);
}
/**
* Determines the closest preceding node for the given ID based on finger
* table, successor list, and predecessor, but without testing the node's
* liveliness.
*
* @param key
* ID to find closest preceding node for.
* @throws NullPointerException
* If ID is <code>null</code>.
* @return Reference on closest preceding node.
*/
final synchronized Node getClosestPrecedingNode(ID key) {
if (key == null) {
NullPointerException e = new NullPointerException(
"ID may not be null!");
this.logger.error("Null pointer", e);
throw e;
}
// determine closest preceding reference of finger table
Node closestNodeFT = this.fingerTable.getClosestPrecedingNode(key);
// determine closest preceding reference of successor list
Node closestNodeSL = this.successorList.getClosestPrecedingNode(key);
// predecessor is appropriate only if it precedes the given id
Node predecessorIfAppropriate = null;
if (this.predecessor != null && key.isInInterval(this.predecessor.nodeID, this.localID)) {
predecessorIfAppropriate = this.predecessor;
}
// with three references which may be null, there are eight (8) cases we
// have to enumerate...
Node closestNode;
if (closestNodeFT == null) {
if (closestNodeSL == null) {
if (predecessorIfAppropriate == null) {
// no reference is appropriate
closestNode = null;
} else {
// only predecessor is appropriate (case should not occur,
// but anyway...
closestNode = predecessorIfAppropriate;
}
} else {
if (predecessorIfAppropriate == null) {
// only reference of successor list is appropriate
closestNode = closestNodeSL;
} else {
// either predecessor or reference of successor list is
// appropriate; determine one of both
if (predecessorIfAppropriate.nodeID.isInInterval(
closestNodeSL.nodeID, key)) {
closestNode = predecessorIfAppropriate;
} else {
closestNode = closestNodeSL;
}
}
}
} else {
if (closestNodeSL == null) {
if (predecessorIfAppropriate == null) {
// only reference of finger table is appropriate
closestNode = closestNodeFT;
} else {
// either predecessor or reference of finger table is
// appropriate; determine one of both
if (predecessorIfAppropriate.nodeID.isInInterval(
closestNodeFT.nodeID, key)) {
closestNode = predecessorIfAppropriate;
} else {
closestNode = closestNodeFT;
}
}
} else {
if (predecessorIfAppropriate == null) {
// either reference of successor list or reference of finger
// table is appropriate; determine one of both
if (closestNodeSL.nodeID.isInInterval(closestNodeFT.nodeID,
key)) {
closestNode = closestNodeSL;
} else {
closestNode = closestNodeFT;
}
} else {
// either of the three reference is appropriate; determine
// first one of the references of successor list and finger
// table is more appropriate and afterwards compare with
// predecessor
if (closestNodeSL.nodeID.isInInterval(closestNodeFT.nodeID,
key)) {
if (predecessorIfAppropriate.nodeID.isInInterval(
closestNodeSL.nodeID, key)) {
closestNode = predecessorIfAppropriate;
} else {
closestNode = closestNodeSL;
}
} else {
if (predecessorIfAppropriate.nodeID.isInInterval(
closestNodeFT.nodeID, key)) {
closestNode = predecessorIfAppropriate;
} else {
closestNode = closestNodeFT;
}
}
}
}
}
this.logger.debug("Closest preceding node of ID "
+ key
+ " at node "
+ this.localID.toString()
+ " is "
+ (closestNode == null ? "null" : "" + closestNode.nodeID)
+ " with closestNodeFT="
+ (closestNodeFT == null ? "null" : "" + closestNodeFT.nodeID)
+ " and closestNodeSL="
+ (closestNodeSL == null ? "null" : "" + closestNodeSL.nodeID)
+ " and predecessor (only if it precedes given ID)="
+ (predecessorIfAppropriate == null ? "null" : ""
+ predecessorIfAppropriate.nodeID));
return closestNode;
}
/**
* Adds the given node reference to the finger table and successor list, if
* appropriate. The reference is NOT set as predecessor, even if is closer
* to this node. Therefore use {@link #addReferenceAsPredecessor(Node)}.
*
* @param newReference
* Reference to be added to the local data structures.
* @throws NullPointerException
* If the given reference is null.
*/
final synchronized void addReference(Node newReference) {
// check parameters
this.checkIfProxy(newReference);
if (newReference == null) {
NullPointerException e = new NullPointerException(
"Node reference to be added must not be null!");
this.logger.error("Null pointer", e);
throw e;
}
if (newReference.nodeID.equals(this.localID)) {
this.logger.info("Reference on myself was not added");
return;
}
this.fingerTable.addReference(newReference);
this.successorList.addSuccessor(newReference);
this.logger.info("Attempted to add reference "
+ newReference.nodeID.toString()
+ " to finger table and successor list. Whether it fit "
+ "or not depends on those data structures.");
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -