?? chordimpl.java
字號:
// 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 + -