/***************************************************************************
* *
* StabilizeTask.java *
* ------------------- *
* date : 16.08.2004 *
* copyright : (C) 2004-2008 Distributed and *
* Mobile Systems Group *
* Lehrstuhl fuer Praktische Informatik *
* Universitaet Bamberg *
* http://www.uni-bamberg.de/pi/ *
* email : sven.kaffille@uni-bamberg.de *
* karsten.loesing@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 static de.uniba.wiai.lspi.util.logging.Logger.LogLevel.DEBUG;
import static de.uniba.wiai.lspi.util.logging.Logger.LogLevel.INFO;
import java.util.List;
import de.uniba.wiai.lspi.chord.com.CommunicationException;
import de.uniba.wiai.lspi.chord.com.Node;
import de.uniba.wiai.lspi.chord.com.RefsAndEntries;
import de.uniba.wiai.lspi.util.logging.Logger;
/**
* Invokes notify method on successor.
*
* @author Karsten Loesing, Sven Kaffille
* @version 1.0.5
*/
final class StabilizeTask implements Runnable {
/**
* Parent object for performing stabilization.
*/
private NodeImpl parent;
/**
* Reference on routing table.
*/
private References references;
private Entries entries;
/**
* Object logger.
*/
protected final static Logger logger = Logger
.getLogger(StabilizeTask.class);
/**
* Creates a new instance, but without starting a thread running it.
*
* @param parent
* Parent object for performing stabilization.
* @param references
* Reference on routing table.
* @throws NullPointerException
* If either of the parameters is <code>null</code>.
*/
StabilizeTask(NodeImpl parent, References references, Entries entries) {
if (parent == null || references == null || entries == null) {
throw new NullPointerException(
"No argument to constructor may be null!");
}
this.parent = parent;
this.references = references;
this.entries = entries;
}
public void run() {
try {
final boolean debugEnabled = StabilizeTask.logger
.isEnabledFor(DEBUG);
final boolean infoEnabled = StabilizeTask.logger.isEnabledFor(INFO);
// start of method
if (debugEnabled) {
StabilizeTask.logger
.debug("Stabilize method has been invoked periodically");
}
// determine successor
Node successor = this.references.getSuccessor();
if (successor == null) {
// nothing to stabilize
if (infoEnabled) {
StabilizeTask.logger
.info("Nothing to stabilize, as successor is null");
return;
}
} else {
// notify successor and obtain its predecessor reference and
// successor list
List<Node> mySuccessorsPredecessorAndSuccessorList;
try {
/*
* NOTIFYING successor.
*/
mySuccessorsPredecessorAndSuccessorList = successor
.notify(this.parent);
if (infoEnabled) {
StabilizeTask.logger
.info("Received response to notify request from "
+ "successor" + successor.getNodeID());
}
} catch (CommunicationException e) {
if (debugEnabled) {
StabilizeTask.logger
.debug(
"Invocation of notify on node "
+ successor.getNodeID()
+ " was not successful due to a "
+ "communication failure! Successor has "
+ "failed during stabilization! "
+ "Removing successor!", e);
}
this.references.removeReference(successor);
return;
}
/*
* 19.06.2007. sven
* Test if our successor has a different
* predecessor than this node.
*/
if ((mySuccessorsPredecessorAndSuccessorList.size() > 0)
&& (mySuccessorsPredecessorAndSuccessorList.get(0) != null)) {
if (!this.parent.getNodeID()
.equals(mySuccessorsPredecessorAndSuccessorList
.get(0).getNodeID())) {
/*
* If it does not know us, we have to fetch all entries
* relevant for us.
*/
RefsAndEntries refsAndEntries = successor
.notifyAndCopyEntries(this.parent);
mySuccessorsPredecessorAndSuccessorList = refsAndEntries
.getRefs();
/*
* and have to store them locally
*/
this.entries.addAll(refsAndEntries.getEntries());
}
}
for (Node newReference : mySuccessorsPredecessorAndSuccessorList) {
this.references.addReference(newReference);
if (debugEnabled) {
logger.debug("Added new reference: " + newReference);
}
}
if (infoEnabled) {
StabilizeTask.logger.info("Invocation of notify on node "
+ successor.getNodeID() + " was successful");
}
}
} catch (Exception e) {
StabilizeTask.logger.warn(
"Unexpected Exception caught in StabilizeTask!", e);
e.printStackTrace();
}
}
}