Add --init option to Daemon to initialize site on daemon start.

The --init option will also upgrade an already existing site and
is processed in non-interactive (batch) mode.

This is a rework of the automatic schema upgrade feature that was
introduced with de980a4ddd and is
reverted with this change. Running init is more generic and also
supports initialization of a new site on daemon start.

Besides automatic upgrade, this feature also makes developers work
more comfortable as it can eliminate running init as a separate
step before running the daemon.

Change-Id: I6a245172529812e42e573413f41424a0497e9539
This commit is contained in:
Sasa Zivkov
2013-05-10 11:15:53 +02:00
parent 383041f948
commit ebd0498956
6 changed files with 32 additions and 130 deletions

View File

@@ -2213,28 +2213,6 @@ If true the deprecated `/query` URL is available to return JSON
and text results for changes. If false, the URL is disabled and and text results for changes. If false, the URL is disabled and
returns 404 to clients. Default is true, enabling `/query`. returns 404 to clients. Default is true, enabling `/query`.
[[site.upgradeSchemaOnStartup]]site.upgradeSchemaOnStartup::
+
Control whether schema upgrade should be done on Gerrit startup. The following
values are supported:
+
* `OFF`
+
No automatic schema upgrade on startup.
+
* `AUTO`
+
Perform schema migration on startup, if necessary. If, as a result of
schema migration, there would be any unused database objects they will
be dropped automatically.
+
* `AUTO_NO_PRUNE`
+
Like `AUTO` but unused database objects will not be pruned.
+
The default is `OFF`.
[[ssh-alias]] Section ssh-alias [[ssh-alias]] Section ssh-alias
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

View File

@@ -15,6 +15,7 @@ SYNOPSIS
[\--console-log] [\--console-log]
[\--slave] [\--slave]
[\--headless] [\--headless]
[\--init]
DESCRIPTION DESCRIPTION
----------- -----------
@@ -63,6 +64,10 @@ This option automatically implies '\--disable-httpd \--enable-sshd'.
Don't start the default Gerrit UI. May be useful when Gerrit is Don't start the default Gerrit UI. May be useful when Gerrit is
run with an alternative UI. run with an alternative UI.
\--init::
Run init before starting the daemon. This will create a new site or
upgrade an existing site.
CONTEXT CONTEXT
------- -------
This command can only be run on a server which has direct This command can only be run on a server which has direct

View File

@@ -38,14 +38,12 @@ import com.google.gerrit.pgm.util.LogFileCompressor;
import com.google.gerrit.pgm.util.RuntimeShutdown; import com.google.gerrit.pgm.util.RuntimeShutdown;
import com.google.gerrit.pgm.util.SiteProgram; import com.google.gerrit.pgm.util.SiteProgram;
import com.google.gerrit.reviewdb.client.AuthType; import com.google.gerrit.reviewdb.client.AuthType;
import com.google.gerrit.reviewdb.server.ReviewDb;
import com.google.gerrit.server.cache.h2.DefaultCacheFactory; import com.google.gerrit.server.cache.h2.DefaultCacheFactory;
import com.google.gerrit.server.config.AuthConfig; import com.google.gerrit.server.config.AuthConfig;
import com.google.gerrit.server.config.AuthConfigModule; import com.google.gerrit.server.config.AuthConfigModule;
import com.google.gerrit.server.config.CanonicalWebUrlModule; import com.google.gerrit.server.config.CanonicalWebUrlModule;
import com.google.gerrit.server.config.CanonicalWebUrlProvider; import com.google.gerrit.server.config.CanonicalWebUrlProvider;
import com.google.gerrit.server.config.GerritGlobalModule; import com.google.gerrit.server.config.GerritGlobalModule;
import com.google.gerrit.server.config.GerritServerConfig;
import com.google.gerrit.server.config.MasterNodeStartup; import com.google.gerrit.server.config.MasterNodeStartup;
import com.google.gerrit.server.contact.HttpContactStoreConnection; import com.google.gerrit.server.contact.HttpContactStoreConnection;
import com.google.gerrit.server.git.ReceiveCommitsExecutorModule; import com.google.gerrit.server.git.ReceiveCommitsExecutorModule;
@@ -55,27 +53,18 @@ import com.google.gerrit.server.mail.SmtpEmailSender;
import com.google.gerrit.server.patch.IntraLineWorkerPool; import com.google.gerrit.server.patch.IntraLineWorkerPool;
import com.google.gerrit.server.plugins.PluginGuiceEnvironment; import com.google.gerrit.server.plugins.PluginGuiceEnvironment;
import com.google.gerrit.server.plugins.PluginModule; import com.google.gerrit.server.plugins.PluginModule;
import com.google.gerrit.server.schema.SchemaUpdater;
import com.google.gerrit.server.schema.SchemaVersionCheck; import com.google.gerrit.server.schema.SchemaVersionCheck;
import com.google.gerrit.server.schema.UpdateUI;
import com.google.gerrit.server.ssh.NoSshKeyCache; import com.google.gerrit.server.ssh.NoSshKeyCache;
import com.google.gerrit.server.ssh.NoSshModule; import com.google.gerrit.server.ssh.NoSshModule;
import com.google.gerrit.sshd.SshKeyCacheImpl; import com.google.gerrit.sshd.SshKeyCacheImpl;
import com.google.gerrit.sshd.SshModule; import com.google.gerrit.sshd.SshModule;
import com.google.gerrit.sshd.commands.MasterCommandModule; import com.google.gerrit.sshd.commands.MasterCommandModule;
import com.google.gerrit.sshd.commands.SlaveCommandModule; import com.google.gerrit.sshd.commands.SlaveCommandModule;
import com.google.gwtorm.jdbc.JdbcExecutor;
import com.google.gwtorm.jdbc.JdbcSchema;
import com.google.gwtorm.server.OrmException;
import com.google.gwtorm.server.SchemaFactory;
import com.google.gwtorm.server.StatementExecutor;
import com.google.inject.AbstractModule; import com.google.inject.AbstractModule;
import com.google.inject.Inject;
import com.google.inject.Injector; import com.google.inject.Injector;
import com.google.inject.Module; import com.google.inject.Module;
import com.google.inject.Provider; import com.google.inject.Provider;
import org.eclipse.jgit.lib.Config;
import org.kohsuke.args4j.Option; import org.kohsuke.args4j.Option;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@@ -121,6 +110,10 @@ public class Daemon extends SiteProgram {
@Option(name = "--headless", usage = "Don't start the UI frontend") @Option(name = "--headless", usage = "Don't start the UI frontend")
private boolean headless; private boolean headless;
@Option(name = "--init", aliases = {"-i"},
usage = "Init site before starting the daemon")
private boolean doInit;
private final LifecycleManager manager = new LifecycleManager(); private final LifecycleManager manager = new LifecycleManager();
private Injector dbInjector; private Injector dbInjector;
private Injector cfgInjector; private Injector cfgInjector;
@@ -141,6 +134,13 @@ public class Daemon extends SiteProgram {
@Override @Override
public int run() throws Exception { public int run() throws Exception {
if (doInit) {
try {
new Init(getSitePath()).run();
} catch (Exception e) {
throw die("Init failed", e);
}
}
mustHaveValidSite(); mustHaveValidSite();
Thread.setDefaultUncaughtExceptionHandler(new UncaughtExceptionHandler() { Thread.setDefaultUncaughtExceptionHandler(new UncaughtExceptionHandler() {
@Override @Override
@@ -176,7 +176,6 @@ public class Daemon extends SiteProgram {
sysInjector = createSysInjector(); sysInjector = createSysInjector();
sysInjector.getInstance(PluginGuiceEnvironment.class) sysInjector.getInstance(PluginGuiceEnvironment.class)
.setCfgInjector(cfgInjector); .setCfgInjector(cfgInjector);
sysInjector.getInstance(SchemaUpgrade.class).upgradeSchema();
manager.add(dbInjector, cfgInjector, sysInjector); manager.add(dbInjector, cfgInjector, sysInjector);
if (sshd) { if (sshd) {
@@ -228,74 +227,6 @@ public class Daemon extends SiteProgram {
} }
} }
static class SchemaUpgrade {
private final Config config;
private final SchemaUpdater updater;
private final SchemaFactory<ReviewDb> schema;
@Inject
SchemaUpgrade(@GerritServerConfig Config config, SchemaUpdater updater,
SchemaFactory<ReviewDb> schema) {
this.config = config;
this.updater = updater;
this.schema = schema;
}
void upgradeSchema() throws OrmException {
SchemaUpgradePolicy policy =
config.getEnum("site", null, "upgradeSchemaOnStartup",
SchemaUpgradePolicy.OFF);
if (policy == SchemaUpgradePolicy.AUTO
|| policy == SchemaUpgradePolicy.AUTO_NO_PRUNE) {
final List<String> pruneList = new ArrayList<String>();
updater.update(new UpdateUI() {
@Override
public void message(String msg) {
log.info(msg);
}
@Override
public boolean yesno(boolean def, String msg) {
return true;
}
@Override
public boolean isBatch() {
return true;
}
@Override
public void pruneSchema(StatementExecutor e, List<String> prune) {
for (String p : prune) {
if (!pruneList.contains(p)) {
pruneList.add(p);
}
}
}
});
if (!pruneList.isEmpty() && policy == SchemaUpgradePolicy.AUTO) {
log.info("Pruning: " + pruneList.toString());
final JdbcSchema db = (JdbcSchema) schema.open();
try {
final JdbcExecutor e = new JdbcExecutor(db);
try {
for (String sql : pruneList) {
e.execute(sql);
}
} finally {
e.close();
}
} finally {
db.close();
}
}
}
}
}
private String myVersion() { private String myVersion() {
return com.google.gerrit.common.Version.getVersion(); return com.google.gerrit.common.Version.getVersion();
} }

View File

@@ -62,6 +62,15 @@ public class Init extends SiteProgram {
@Option(name = "--no-auto-start", usage = "Don't automatically start daemon after init") @Option(name = "--no-auto-start", usage = "Don't automatically start daemon after init")
private boolean noAutoStart; private boolean noAutoStart;
public Init() {
}
public Init(File sitePath) {
super(sitePath);
batchMode = true;
noAutoStart = true;
}
@Override @Override
public int run() throws Exception { public int run() throws Exception {
ErrorLogFile.errorOnlyConsole(); ErrorLogFile.errorOnlyConsole();

View File

@@ -1,28 +0,0 @@
// Copyright (C) 2012 The Android Open Source Project
//
// 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 com.google.gerrit.pgm;
/** Policy for auto upgrading schema on server startup */
public enum SchemaUpgradePolicy {
/** Perform schema migration if necessary and prune unused objects */
AUTO,
/** Like AUTO but don't prune unused objects */
AUTO_NO_PRUNE,
/** No automatic schema upgrade */
OFF
}

View File

@@ -51,6 +51,13 @@ public abstract class SiteProgram extends AbstractProgram {
@Option(name = "--site-path", aliases = {"-d"}, usage = "Local directory containing site data") @Option(name = "--site-path", aliases = {"-d"}, usage = "Local directory containing site data")
private File sitePath = new File("."); private File sitePath = new File(".");
protected SiteProgram() {
}
protected SiteProgram(File sitePath) {
this.sitePath = sitePath;
}
/** @return the site path specified on the command line. */ /** @return the site path specified on the command line. */
protected File getSitePath() { protected File getSitePath() {
File path = sitePath.getAbsoluteFile(); File path = sitePath.getAbsoluteFile();