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
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
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

View File

@@ -15,6 +15,7 @@ SYNOPSIS
[\--console-log]
[\--slave]
[\--headless]
[\--init]
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
run with an alternative UI.
\--init::
Run init before starting the daemon. This will create a new site or
upgrade an existing site.
CONTEXT
-------
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.SiteProgram;
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.config.AuthConfig;
import com.google.gerrit.server.config.AuthConfigModule;
import com.google.gerrit.server.config.CanonicalWebUrlModule;
import com.google.gerrit.server.config.CanonicalWebUrlProvider;
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.contact.HttpContactStoreConnection;
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.plugins.PluginGuiceEnvironment;
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.UpdateUI;
import com.google.gerrit.server.ssh.NoSshKeyCache;
import com.google.gerrit.server.ssh.NoSshModule;
import com.google.gerrit.sshd.SshKeyCacheImpl;
import com.google.gerrit.sshd.SshModule;
import com.google.gerrit.sshd.commands.MasterCommandModule;
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.Inject;
import com.google.inject.Injector;
import com.google.inject.Module;
import com.google.inject.Provider;
import org.eclipse.jgit.lib.Config;
import org.kohsuke.args4j.Option;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -121,6 +110,10 @@ public class Daemon extends SiteProgram {
@Option(name = "--headless", usage = "Don't start the UI frontend")
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 Injector dbInjector;
private Injector cfgInjector;
@@ -141,6 +134,13 @@ public class Daemon extends SiteProgram {
@Override
public int run() throws Exception {
if (doInit) {
try {
new Init(getSitePath()).run();
} catch (Exception e) {
throw die("Init failed", e);
}
}
mustHaveValidSite();
Thread.setDefaultUncaughtExceptionHandler(new UncaughtExceptionHandler() {
@Override
@@ -176,7 +176,6 @@ public class Daemon extends SiteProgram {
sysInjector = createSysInjector();
sysInjector.getInstance(PluginGuiceEnvironment.class)
.setCfgInjector(cfgInjector);
sysInjector.getInstance(SchemaUpgrade.class).upgradeSchema();
manager.add(dbInjector, cfgInjector, sysInjector);
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() {
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")
private boolean noAutoStart;
public Init() {
}
public Init(File sitePath) {
super(sitePath);
batchMode = true;
noAutoStart = true;
}
@Override
public int run() throws Exception {
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")
private File sitePath = new File(".");
protected SiteProgram() {
}
protected SiteProgram(File sitePath) {
this.sitePath = sitePath;
}
/** @return the site path specified on the command line. */
protected File getSitePath() {
File path = sitePath.getAbsoluteFile();