Automatic schema upgrade on Gerrit startup

In case when Gerrit administrator(s) don't have a direct access to the
file system where the review site is located it gets difficult to
perform a schema upgrade (run the init program). For such cases it is
convenient if Gerrit performs schema upgrade automatically on its
startup.

Since this is a potentially dangerous operation, by default it will not
be performed. Configuration parameter site.upgradeSchemaOnStartup is
used to switch on automatic schema upgrade. It has 3 possible values:

  * OFF - no automatic schema upgrade (default)
  * AUTO - automatic schema upgrade and drop of unused DB objects
  * AUTO_NO_PRUNE - like AUTO but without dropping unused DB objects

Change-Id: Ief1bf1135fde74146e5a5fdd25f510a4eeae0a73
Signed-off-by: Edwin Kempin <edwin.kempin@sap.com>
Signed-off-by: Sasa Zivkov <sasa.zivkov@sap.com>
This commit is contained in:
Sasa Zivkov
2012-06-14 14:57:53 +02:00
parent 23c571899e
commit de980a4ddd
3 changed files with 130 additions and 0 deletions

View File

@@ -1938,6 +1938,28 @@ 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

@@ -35,12 +35,14 @@ 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;
@@ -49,15 +51,24 @@ import com.google.gerrit.server.mail.SignedTokenEmailTokenVerifier;
import com.google.gerrit.server.mail.SmtpEmailSender; import com.google.gerrit.server.mail.SmtpEmailSender;
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.NoSshModule; import com.google.gerrit.server.ssh.NoSshModule;
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.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;
@@ -145,6 +156,7 @@ 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) {
@@ -192,6 +204,74 @@ 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

@@ -0,0 +1,28 @@
// 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
}