/* * Mojito Distributed Hash Table (Mojito DHT) * Copyright (C) 2006-2007 LimeWire LLC * * 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. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ package org.limewire.mojito.manager; import java.net.SocketAddress; import java.util.Set; import org.limewire.mojito.Context; import org.limewire.mojito.concurrent.DHTFuture; import org.limewire.mojito.concurrent.DHTFutureTask; import org.limewire.mojito.concurrent.DHTTask; import org.limewire.mojito.result.BootstrapResult; import org.limewire.mojito.routing.Contact; /** * Manages the bootstrap process and determines * whether or not the local Node is bootstrapped. */ public class BootstrapManager extends AbstractManager<BootstrapResult> { /** * The BootstrapFuture object that will contain the result * of our bootstrap. * LOCKING: this */ private BootstrapFuture future = null; /** * A flag for whether or not we're bootstrapped */ private boolean bootstrapped = false; public BootstrapManager(Context context) { super(context); } /** * Returns true if this Node has bootstrapped successfully. */ public synchronized boolean isBootstrapped() { return bootstrapped; } /** * An internal method to set the bootstrapped flag. * Meant for internal use only. */ public synchronized void setBootstrapped(boolean bootstrapped) { this.bootstrapped = bootstrapped; } /** * Returns true if this Node is currently bootstrapping. */ public synchronized boolean isBootstrapping() { return future != null; } public void stop() { BootstrapFuture f; synchronized(this) { f = future; future = null; } if (f != null) f.cancel(true); } /** * Tries to bootstrap the local Node from the given Contact. */ public DHTFuture<BootstrapResult> bootstrap(Contact node) { if (node == null) { throw new NullPointerException("Contact is null"); } if (node.equals(context.getLocalNode())) { throw new IllegalArgumentException("Cannot bootstrap from local Node"); } // Make sure there is only one bootstrap process active! // Having parallel bootstrap processes is too expensive! stop(); // Bootstrap... BootstrapProcess process = new BootstrapProcess(context, this, node); BootstrapFuture future = new BootstrapFuture(process); synchronized (this) { this.future = future; } context.getDHTExecutorService().execute(future); return future; } /** * Tries to bootstrap the local Node from any of the given SocketAddresses. */ public DHTFuture<BootstrapResult> bootstrap(Set<? extends SocketAddress> dst) { if (dst == null) { throw new NullPointerException("Set<SocketAddress> is null"); } // Make sure there is only one bootstrap process active! // Having parallel bootstrap processes is too expensive! stop(); // Bootstrap... BootstrapProcess process = new BootstrapProcess(context, this, dst); BootstrapFuture future = new BootstrapFuture(process); synchronized (this) { this.future = future; } context.getDHTExecutorService().execute(future); return future; } private class BootstrapFuture extends DHTFutureTask<BootstrapResult> { public BootstrapFuture(DHTTask<BootstrapResult> task) { super(context, task); } @Override protected void done() { stop(); } } }