/*
* Copyright 2013 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.builder;
import java.security.KeyPair;
import net.tomp2p.connection.ChannelCreator;
import net.tomp2p.connection.DefaultConnectionConfiguration;
import net.tomp2p.futures.BaseFutureAdapter;
import net.tomp2p.futures.FutureChannelCreator;
import net.tomp2p.futures.FutureDone;
import net.tomp2p.futures.FutureRouting;
import net.tomp2p.p2p.Peer;
import net.tomp2p.p2p.RoutingConfiguration;
import net.tomp2p.utils.Utils;
/**
* Set the configuration options for the shutdown command. The shutdown does first a rounting, searches for its close
* peers and then send a quit message so that the other peers knows that this peer is offline.
*
* @author Thomas Bocek
*
*/
public class ShutdownBuilder extends DefaultConnectionConfiguration implements SignatureBuilder<ShutdownBuilder> {
private static final FutureDone<Void> FUTURE_SHUTDOWN = new FutureDone<Void>().failed("shutdown");
private final Peer peer;
private KeyPair keyPair = null;
private RoutingConfiguration routingConfiguration;
private boolean forceRoutingOnlyToSelf = false;
/**
* Constructor.
*
* @param peer
* The peer that runs the routing and quit messages
*/
public ShutdownBuilder(final Peer peer) {
this.peer = peer;
}
/**
* Start the shutdown. This method returns immediately with a future object. The future object can be used to block
* or add a listener.
*
* @return The future object
*/
public FutureDone<Void> start() {
if (peer.isShutdown()) {
return FUTURE_SHUTDOWN;
}
forceUDP();
if (routingConfiguration == null) {
routingConfiguration = new RoutingConfiguration(8, 10, 2);
}
int conn = routingConfiguration.parallel();
FutureChannelCreator fcc = peer.connectionBean().reservation().create(conn, 0);
final FutureDone<Void> futureShutdown = new FutureDone<Void> ();
Utils.addReleaseListener(fcc, futureShutdown);
fcc.addListener(new BaseFutureAdapter<FutureChannelCreator>() {
@Override
public void operationComplete(final FutureChannelCreator futureChannelCreator) throws Exception {
if (futureChannelCreator.isSuccess()) {
ChannelCreator cc = futureChannelCreator.channelCreator();
RoutingBuilder routingBuilder = BootstrapBuilder.createBuilder(routingConfiguration, forceRoutingOnlyToSelf);
routingBuilder.locationKey(peer.peerID());
FutureRouting futureRouting = peer.distributedRouting().quit(routingBuilder, cc);
futureRouting.addListener(new BaseFutureAdapter<FutureRouting>() {
@Override
public void operationComplete(FutureRouting future) throws Exception {
if(future.isSuccess()) {
futureShutdown.done();
} else {
futureShutdown.failed(future);
}
}
});
} else {
futureShutdown.failed(futureChannelCreator);
}
}
});
return futureShutdown;
}
/**
* @return Set to true if the message should be signed. For protecting an
* entry, this needs to be set to true.
*/
public boolean isSign() {
return keyPair != null;
}
/**
* @param signMessage
* Set to true if the message should be signed. For protecting an
* entry, this needs to be set to true.
* @return This class
*/
public ShutdownBuilder sign(final boolean signMessage) {
if (signMessage) {
sign();
} else {
this.keyPair = null;
}
return this;
}
/**
* @return Set to true if the message should be signed. For protecting an
* entry, this needs to be set to true.
*/
public ShutdownBuilder sign() {
this.keyPair = peer.peerBean().keyPair();
return this;
}
/**
* @param keyPair
* The keyPair to sing the complete message. The key will be
* attached to the message and stored potentially with a data
* object (if there is such an object in the message).
* @return This class
*/
public ShutdownBuilder keyPair(KeyPair keyPair) {
this.keyPair = keyPair;
return this;
}
/**
* @return The current keypair to sign the message. If null, no signature is
* applied.
*/
public KeyPair keyPair() {
return keyPair;
}
public RoutingConfiguration routingConfiguration() {
return routingConfiguration;
}
public ShutdownBuilder routingConfiguration(RoutingConfiguration routingConfiguration) {
this.routingConfiguration = routingConfiguration;
return this;
}
public boolean isForceRoutingOnlyToSelf() {
return forceRoutingOnlyToSelf;
}
public ShutdownBuilder forceRoutingOnlyToSelf() {
this.forceRoutingOnlyToSelf = true;
return this;
}
public ShutdownBuilder forceRoutingOnlyToSelf(boolean forceRoutingOnlyToSelf) {
this.forceRoutingOnlyToSelf = forceRoutingOnlyToSelf;
return this;
}
}