blob: 4e504955c57c3b0609976c9d466d372ad9ce53f1 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more contributor license
* agreements. See the NOTICE file distributed with this work for additional information regarding
* copyright ownership. The ASF licenses this file to You 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 org.apache.geode.internal;
import java.io.File;
import java.io.IOException;
import java.net.ConnectException;
import java.net.InetAddress;
import java.util.Properties;
import org.apache.logging.log4j.Logger;
import org.apache.geode.SystemFailure;
import org.apache.geode.annotations.internal.MakeNotStatic;
import org.apache.geode.distributed.internal.DistributionConfig;
import org.apache.geode.distributed.internal.InternalDistributedSystem;
import org.apache.geode.distributed.internal.InternalLocator;
import org.apache.geode.distributed.internal.tcpserver.TcpClient;
import org.apache.geode.logging.internal.executors.LoggingThread;
import org.apache.geode.logging.internal.log4j.api.LogService;
/**
* This class is used to work with a managed VM that hosts a
* {@link org.apache.geode.distributed.Locator}.
*
* @since GemFire 2.0
*/
public class DistributionLocator {
private static final Logger logger = LogService.getLogger();
public static final String TEST_OVERRIDE_DEFAULT_PORT_PROPERTY =
DistributionConfig.GEMFIRE_PREFIX + "test.DistributionLocator.OVERRIDE_DEFAULT_PORT";
/** Default file name for locator log: <code>"locator.log"</code> */
public static final String DEFAULT_LOG_FILE = "locator.log";
public static final String DEFAULT_STARTUP_LOG_FILE = "start_locator.log";
public static final int DEFAULT_LOCATOR_PORT = 10334;
public static final boolean LOAD_SHARED_CONFIGURATION = false;
public static int parsePort(String portOption) {
if (portOption == null || portOption.equals("")) {
return Integer.getInteger(TEST_OVERRIDE_DEFAULT_PORT_PROPERTY, DEFAULT_LOCATOR_PORT);
} else {
int result = Integer.parseInt(portOption);
if (result < 1 || result > 65535) {
throw new IllegalArgumentException(
"The -port= argument must be greater than 0 and less than 65536.");
} else {
return result;
}
}
}
public static void stop(InetAddress addr, int port) {
try {
new TcpClient().stop(addr, port);
} catch (ConnectException ignore) {
// must not be running
}
}
@MakeNotStatic
private static boolean shutdown = false;
@MakeNotStatic
private static File lockFile = null;
private static final File directory = (new File("")).getAbsoluteFile();
/**
* Cleans up the artifacts left by this managed locator VM.
*/
protected static void shutdown(int port, InetAddress address) throws IOException {
if (shutdown) {
return;
}
shutdown = true;
if (directory != null) {
ManagerInfo.setLocatorStopping(directory, port, address);
}
if (lockFile != null) {
if (!lockFile.delete() && lockFile.exists()) {
IOException e = new IOException("Unable to delete " + lockFile.getAbsolutePath());
e.printStackTrace(); // What else to do?
}
}
logger.info("Locator stopped");
}
public static void main(String args[]) {
if (args.length == 0 || args.length > 6) {
System.err.println(
"Usage: port [bind-address] [peerLocator] [serverLocator] [hostname-for-clients]");
System.err
.println("A zero-length address will bind to localhost");
System.err.println(
"A zero-length gemfire-properties-file will mean use the default search path");
System.err.println(
"peerLocator and serverLocator both default to true");
System.err.println(
"A zero-length hostname-for-clients will default to bind-address");
ExitCode.FATAL.doSystemExit();
} else {
shutdown = false;
}
SystemFailure.loadEmergencyClasses();
final int port = parsePort(args[0]);
InetAddress address = null;
boolean peerLocator = true;
boolean serverLocator = true;
String hostnameForClients = null;
try {
if (args.length > 1 && !args[1].equals("")) {
if (!SystemAdmin.validLocalAddress(args[1])) {
System.err.println(
String.format("'%s' is not a valid IP address for this machine",
args[1]));
ExitCode.FATAL.doSystemExit();
}
address = InetAddress.getByName(args[1]);
} else {
// address = null; // was InetAddress.getLocalHost(); (redundant assignment)
}
if (args.length > 2) {
peerLocator = "true".equalsIgnoreCase(args[2]);
}
if (args.length > 3) {
serverLocator = "true".equalsIgnoreCase(args[3]);
}
if (args.length > 4) {
hostnameForClients = args[4];
}
if (!Boolean.getBoolean(InternalDistributedSystem.DISABLE_SHUTDOWN_HOOK_PROPERTY)) {
final InetAddress faddress = address;
Runtime.getRuntime()
.addShutdownHook(new LoggingThread("LocatorShutdownThread", false, () -> {
try {
DistributionLocator.shutdown(port, faddress);
} catch (IOException e) {
e.printStackTrace();
}
}));
}
lockFile = ManagerInfo.setLocatorStarting(directory, port, address);
lockFile.deleteOnExit();
try {
InternalLocator locator = InternalLocator.startLocator(port, new File(DEFAULT_LOG_FILE),
null, null, address, true, (Properties) null, hostnameForClients);
ManagerInfo.setLocatorStarted(directory, port, address);
locator.waitToStop();
} finally {
shutdown(port, address);
}
} catch (InterruptedException ex) {
// We were interrupted while waiting for the locator to stop.
// No big deal.
} catch (java.net.BindException ex) {
logger.fatal("Could not bind locator to {}[{}]",
new Object[] {address, port});
ExitCode.FATAL.doSystemExit();
} catch (Exception ex) {
logger.fatal("Could not start locator",
ex);
ExitCode.FATAL.doSystemExit();
}
}
}