]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-8798 pass sonar.search.javaOpts in a file to ES
authorDaniel Schwarz <daniel.schwarz@sonarsource.com>
Fri, 4 Aug 2017 12:09:07 +0000 (14:09 +0200)
committerDaniel Schwarz <bartfastiel@users.noreply.github.com>
Wed, 9 Aug 2017 13:09:54 +0000 (15:09 +0200)
server/sonar-process-monitor/src/main/java/org/sonar/application/process/CommandFactoryImpl.java
server/sonar-process-monitor/src/main/java/org/sonar/application/process/EsCommand.java
server/sonar-process-monitor/src/main/java/org/sonar/application/process/ProcessLauncherImpl.java
server/sonar-process/src/main/java/org/sonar/process/ProcessProperties.java
sonar-application/src/main/assembly/conf/sonar.properties

index 093b44ef20de7b295fb49dd8f4ffed04538cfe8c..fdb296347a7a119792bd1430789fd418e4e7791f 100644 (file)
@@ -20,6 +20,7 @@
 package org.sonar.application.process;
 
 import java.io.File;
+import java.nio.file.Path;
 import java.util.Map;
 import java.util.Optional;
 import java.util.Properties;
@@ -64,15 +65,22 @@ public class CommandFactoryImpl implements CommandFactory {
     Map<String, String> settingsMap = new EsSettings(this.settings.getProps()).build();
 
     File logDir = new File(settingsMap.get("path.logs"));
+    File confDir = new File(settingsMap.get("path.conf"));
+    Path jvmOptionsFile = confDir.toPath().resolve("jvm.options");
     EsCommand res = new EsCommand(ProcessId.ELASTICSEARCH)
       .setWorkDir(executable.getParentFile().getParentFile())
       .setExecutable(executable)
-      .setConfDir(new File(settingsMap.get("path.conf")))
+      .setConfDir(confDir)
       .setLog4j2Properties(buildLog4j2Properties(logDir))
       .setArguments(this.settings.getProps().rawProperties())
       .setClusterName(settingsMap.get("cluster.name"))
       .setHost(settingsMap.get("network.host"))
-      .setPort(Integer.valueOf(settingsMap.get("transport.tcp.port")));
+      .setPort(Integer.valueOf(settingsMap.get("transport.tcp.port")))
+      .addJvmOption(settings.getProps().nonNullValue(ProcessProperties.SEARCH_JAVA_OPTS))
+      .addJvmOption(settings.getProps().nonNullValue(ProcessProperties.SEARCH_JAVA_ADDITIONAL_OPTS))
+      .setJvmOptionsFile(jvmOptionsFile)
+      .setEnvVariable("ES_JVM_OPTIONS", jvmOptionsFile.toString())
+      ;
 
     settingsMap.forEach((key, value) -> res.addEsOption("-E" + key + "=" + value));
 
index 5557978388b4ebe030f939e626d8521d839eb6d5..3e787eb6736edf96452a71150bffdb9b696e1af4 100644 (file)
@@ -20,6 +20,7 @@
 package org.sonar.application.process;
 
 import java.io.File;
+import java.nio.file.Path;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Properties;
@@ -33,6 +34,8 @@ public class EsCommand extends AbstractCommand<EsCommand> {
   private int port;
   private Properties log4j2Properties;
   private List<String> esOptions = new ArrayList<>();
+  private List<String> jvmOptions = new ArrayList<>();
+  private Path jvmOptionsFile;
 
   public EsCommand(ProcessId id) {
     super(id);
@@ -102,4 +105,24 @@ public class EsCommand extends AbstractCommand<EsCommand> {
     }
     return this;
   }
+
+  public List<String> getJvmOptions() {
+    return jvmOptions;
+  }
+
+  public EsCommand addJvmOption(String s) {
+    if (!s.isEmpty()) {
+      jvmOptions.add(s);
+    }
+    return this;
+  }
+
+  public Path getJvmOptionsFile() {
+    return jvmOptionsFile;
+  }
+
+  public EsCommand setJvmOptionsFile(Path jvmOptionsFile) {
+    this.jvmOptionsFile = jvmOptionsFile;
+    return this;
+  }
 }
index f6817b6ab924facf9fdc14b6fcf13f01eab9b8a5..b849c5f52c939788b683546be45782baf8aeb20f 100644 (file)
@@ -23,12 +23,17 @@ import java.io.File;
 import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.OutputStream;
+import java.nio.charset.Charset;
+import java.nio.file.Files;
+import java.nio.file.Path;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
 import java.util.Map;
 import java.util.Properties;
 import java.util.function.Supplier;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
 import org.apache.commons.io.IOUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -43,6 +48,11 @@ import static org.sonar.process.ProcessEntryPoint.PROPERTY_TERMINATION_TIMEOUT;
 
 public class ProcessLauncherImpl implements ProcessLauncher {
   private static final Logger LOG = LoggerFactory.getLogger(ProcessLauncherImpl.class);
+  public static final String ELASTICSEARCH_JVM_OPTIONS_HEADER = "# This file has been automatically generated by SonarQube during startup.\n" +
+    "# Please use the sonar.search.javaOpts in sonar.properties to specify jvm options for Elasticsearch\n" +
+    "\n" +
+    "# DO NOT EDIT THIS FILE\n" +
+    "\n";
 
   private final File tempDir;
   private final AllProcessesCommands allProcessesCommands;
@@ -125,9 +135,26 @@ public class ProcessLauncherImpl implements ProcessLauncher {
     commands.add(esCommand.getExecutable().getAbsolutePath());
     commands.addAll(esCommand.getEsOptions());
 
+    writeJvmOptions(esCommand);
+
     return create(esCommand, commands);
   }
 
+  private void writeJvmOptions(EsCommand esCommand) {
+    Path jvmOptionsFile = esCommand.getJvmOptionsFile();
+    String jvmOptions = esCommand.getJvmOptions()
+      .stream()
+      .map(s -> s.split(" (?=-)"))// FIXME this pattern does not allow escaping
+      .flatMap(Arrays::stream)
+      .collect(Collectors.joining("\n"));
+    String jvmOptionsContent = ELASTICSEARCH_JVM_OPTIONS_HEADER + jvmOptions;
+    try {
+      Files.write(jvmOptionsFile, jvmOptionsContent.getBytes(Charset.forName("UTF-8")));
+    } catch (IOException e) {
+      throw new RuntimeException("Cannot write Elasticsearch jvm options file", e);
+    }
+  }
+
   private ProcessBuilder create(JavaCommand javaCommand) {
     List<String> commands = new ArrayList<>();
     commands.add(buildJavaPath());
index 959788fb933d5b77847efafcd7e57222d606c717..c2f61f644e9254b304bf3b25823a147db22e9138 100644 (file)
@@ -121,9 +121,25 @@ public class ProcessProperties {
     Properties defaults = new Properties();
     defaults.put(SEARCH_HOST, InetAddress.getLoopbackAddress().getHostAddress());
     defaults.put(SEARCH_PORT, "9001");
-    defaults.put(SEARCH_JAVA_OPTS, "-Xmx1G -Xms256m -Xss256k -Djna.nosys=true " +
-      "-XX:+UseParNewGC -XX:+UseConcMarkSweepGC -XX:CMSInitiatingOccupancyFraction=75 -XX:+UseCMSInitiatingOccupancyOnly " +
-      "-XX:+HeapDumpOnOutOfMemoryError");
+    defaults.put(SEARCH_JAVA_OPTS, "-Xms1g" +
+      " -Xmx1g"  +
+      " -XX:+UseConcMarkSweepGC"  +
+      " -XX:CMSInitiatingOccupancyFraction=75"  +
+      " -XX:+UseCMSInitiatingOccupancyOnly"  +
+      " -XX:+AlwaysPreTouch"  +
+      " -server"  +
+      " -Xss1m"  +
+      " -Djava.awt.headless=true"  +
+      " -Dfile.encoding=UTF-8"  +
+      " -Djna.nosys=true"  +
+      " -Djdk.io.permissionsUseCanonicalPath=true"  +
+      " -Dio.netty.noUnsafe=true"  +
+      " -Dio.netty.noKeySetOptimization=true"  +
+      " -Dio.netty.recycler.maxCapacityPerThread=0"  +
+      " -Dlog4j.shutdownHookEnabled=false"  +
+      " -Dlog4j2.disable.jmx=true"  +
+      " -Dlog4j.skipJansi=true"  +
+      " -XX:+HeapDumpOnOutOfMemoryError");
     defaults.put(SEARCH_JAVA_ADDITIONAL_OPTS, "");
 
     defaults.put(PATH_DATA, "data");
index 4b167d014e7916be07fdc0425e5973ac89d71565..5b5c6e054ec9ea9a8216caae4a577e9de357c9de 100644 (file)
 #--------------------------------------------------------------------------------------------------
 # ELASTICSEARCH
 # Elasticsearch is used to facilitate fast and accurate information retrieval.
-# It is executed in a dedicated Java process. Default heap size is 1Gb.
+# It is executed in a dedicated Java process. Default heap size is 2Gb.
 
 # JVM options of Elasticsearch process
-#    Recommendations:
-#
-#    Use HotSpot Server VM. The property -server should be added if server mode
-#    is not enabled by default on your environment:
-#    http://docs.oracle.com/javase/8/docs/technotes/guides/vm/server-class.html
-#
-#sonar.search.javaOpts=-Xmx1G -Xms256m -Xss256k -Djna.nosys=true \
-#  -XX:+UseParNewGC -XX:+UseConcMarkSweepGC -XX:CMSInitiatingOccupancyFraction=75 \
-#  -XX:+UseCMSInitiatingOccupancyOnly -XX:+HeapDumpOnOutOfMemoryError
+#sonar.search.javaOpts=-Xms2g \
+# -Xmx2g \
+# -XX:+UseConcMarkSweepGC \
+# -XX:CMSInitiatingOccupancyFraction=75 \
+# -XX:+UseCMSInitiatingOccupancyOnly \
+# -XX:+AlwaysPreTouch \
+# -server \
+# -Xss1m \
+# -Djava.awt.headless=true \
+# -Dfile.encoding=UTF-8 \
+# -Djna.nosys=true \
+# -Djdk.io.permissionsUseCanonicalPath=true \
+# -Dio.netty.noUnsafe=true \
+# -Dio.netty.noKeySetOptimization=true \
+# -Dio.netty.recycler.maxCapacityPerThread=0 \
+# -Dlog4j.shutdownHookEnabled=false \
+# -Dlog4j2.disable.jmx=true \
+# -Dlog4j.skipJansi=true \
+# -XX:+HeapDumpOnOutOfMemoryError
 
 # Same as previous property, but allows to not repeat all other settings like -Xmx
 #sonar.search.javaAdditionalOpts=