Stop creating the entire SchemaVersion chain at runtime
Running Gerrit servers build every Schema_NNN instance at server startup due to the Guice binding for @Current SchemaVersion implicitly linking to everything through the constructors and the Guice injector running in mode PRODUCTION, where all dependencies are resolved immediately at startup. Instead get the binary version off the C constant, which does not require loading all classes. Use a new injector with mode DEVELOPMENT to support lazy loading of older versions only as necessary. Change-Id: I9c62f2603f61bdd58a800b1d03b10c28a0c78773
This commit is contained in:
@@ -1,27 +0,0 @@
|
|||||||
// Copyright (C) 2009 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.server.schema;
|
|
||||||
|
|
||||||
import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
|
||||||
|
|
||||||
import com.google.inject.BindingAnnotation;
|
|
||||||
|
|
||||||
import java.lang.annotation.Retention;
|
|
||||||
|
|
||||||
/** Indicates the {@link SchemaVersion} is the current one. */
|
|
||||||
@Retention(RUNTIME)
|
|
||||||
@BindingAnnotation
|
|
||||||
public @interface Current {
|
|
||||||
}
|
|
@@ -46,23 +46,19 @@ public class SchemaCreator {
|
|||||||
private final PersonIdent serverUser;
|
private final PersonIdent serverUser;
|
||||||
private final DataSourceType dataSourceType;
|
private final DataSourceType dataSourceType;
|
||||||
|
|
||||||
private final int versionNbr;
|
|
||||||
|
|
||||||
private AccountGroup admin;
|
private AccountGroup admin;
|
||||||
private AccountGroup batch;
|
private AccountGroup batch;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public SchemaCreator(SitePaths site,
|
public SchemaCreator(SitePaths site,
|
||||||
@Current SchemaVersion version,
|
|
||||||
AllProjectsCreator ap,
|
AllProjectsCreator ap,
|
||||||
AllUsersCreator auc,
|
AllUsersCreator auc,
|
||||||
@GerritPersonIdent PersonIdent au,
|
@GerritPersonIdent PersonIdent au,
|
||||||
DataSourceType dst) {
|
DataSourceType dst) {
|
||||||
this(site.site_path, version, ap, auc, au, dst);
|
this(site.site_path, ap, auc, au, dst);
|
||||||
}
|
}
|
||||||
|
|
||||||
public SchemaCreator(@SitePath File site,
|
public SchemaCreator(@SitePath File site,
|
||||||
@Current SchemaVersion version,
|
|
||||||
AllProjectsCreator ap,
|
AllProjectsCreator ap,
|
||||||
AllUsersCreator auc,
|
AllUsersCreator auc,
|
||||||
@GerritPersonIdent PersonIdent au,
|
@GerritPersonIdent PersonIdent au,
|
||||||
@@ -72,7 +68,6 @@ public class SchemaCreator {
|
|||||||
allUsersCreator = auc;
|
allUsersCreator = auc;
|
||||||
serverUser = au;
|
serverUser = au;
|
||||||
dataSourceType = dst;
|
dataSourceType = dst;
|
||||||
versionNbr = version.getVersionNbr();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void create(final ReviewDb db) throws OrmException, IOException,
|
public void create(final ReviewDb db) throws OrmException, IOException,
|
||||||
@@ -86,7 +81,7 @@ public class SchemaCreator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
final CurrentSchemaVersion sVer = CurrentSchemaVersion.create();
|
final CurrentSchemaVersion sVer = CurrentSchemaVersion.create();
|
||||||
sVer.versionNbr = versionNbr;
|
sVer.versionNbr = SchemaVersion.getBinaryVersion();
|
||||||
db.schemaVersion().insert(Collections.singleton(sVer));
|
db.schemaVersion().insert(Collections.singleton(sVer));
|
||||||
|
|
||||||
initSystemConfig(db);
|
initSystemConfig(db);
|
||||||
|
@@ -32,8 +32,6 @@ import org.eclipse.jgit.lib.PersonIdent;
|
|||||||
public class SchemaModule extends FactoryModule {
|
public class SchemaModule extends FactoryModule {
|
||||||
@Override
|
@Override
|
||||||
protected void configure() {
|
protected void configure() {
|
||||||
install(new SchemaVersion.Module());
|
|
||||||
|
|
||||||
bind(PersonIdent.class).annotatedWith(GerritPersonIdent.class)
|
bind(PersonIdent.class).annotatedWith(GerritPersonIdent.class)
|
||||||
.toProvider(GerritPersonIdentProvider.class);
|
.toProvider(GerritPersonIdentProvider.class);
|
||||||
|
|
||||||
|
@@ -17,13 +17,23 @@ package com.google.gerrit.server.schema;
|
|||||||
import com.google.gerrit.reviewdb.client.CurrentSchemaVersion;
|
import com.google.gerrit.reviewdb.client.CurrentSchemaVersion;
|
||||||
import com.google.gerrit.reviewdb.client.SystemConfig;
|
import com.google.gerrit.reviewdb.client.SystemConfig;
|
||||||
import com.google.gerrit.reviewdb.server.ReviewDb;
|
import com.google.gerrit.reviewdb.server.ReviewDb;
|
||||||
|
import com.google.gerrit.server.GerritPersonIdent;
|
||||||
|
import com.google.gerrit.server.config.AllProjectsName;
|
||||||
|
import com.google.gerrit.server.config.AnonymousCowardName;
|
||||||
import com.google.gerrit.server.config.SitePaths;
|
import com.google.gerrit.server.config.SitePaths;
|
||||||
|
import com.google.gerrit.server.git.GitRepositoryManager;
|
||||||
import com.google.gwtorm.server.OrmException;
|
import com.google.gwtorm.server.OrmException;
|
||||||
import com.google.gwtorm.server.SchemaFactory;
|
import com.google.gwtorm.server.SchemaFactory;
|
||||||
|
import com.google.inject.AbstractModule;
|
||||||
|
import com.google.inject.Guice;
|
||||||
import com.google.inject.Inject;
|
import com.google.inject.Inject;
|
||||||
|
import com.google.inject.Injector;
|
||||||
|
import com.google.inject.Key;
|
||||||
import com.google.inject.Provider;
|
import com.google.inject.Provider;
|
||||||
|
import com.google.inject.Stage;
|
||||||
|
|
||||||
import org.eclipse.jgit.errors.ConfigInvalidException;
|
import org.eclipse.jgit.errors.ConfigInvalidException;
|
||||||
|
import org.eclipse.jgit.lib.PersonIdent;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
@@ -37,12 +47,46 @@ public class SchemaUpdater {
|
|||||||
private final Provider<SchemaVersion> updater;
|
private final Provider<SchemaVersion> updater;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
SchemaUpdater(final SchemaFactory<ReviewDb> schema, final SitePaths site,
|
SchemaUpdater(SchemaFactory<ReviewDb> schema,
|
||||||
final SchemaCreator creator, @Current final Provider<SchemaVersion> update) {
|
SitePaths site,
|
||||||
|
SchemaCreator creator,
|
||||||
|
Injector parent) {
|
||||||
this.schema = schema;
|
this.schema = schema;
|
||||||
this.site = site;
|
this.site = site;
|
||||||
this.creator = creator;
|
this.creator = creator;
|
||||||
this.updater = update;
|
this.updater = buildInjector(parent).getProvider(SchemaVersion.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Injector buildInjector(final Injector parent) {
|
||||||
|
// Use DEVELOPMENT mode to allow lazy initialization of the
|
||||||
|
// graph. This avoids touching ancient schema versions that
|
||||||
|
// are behind this installation's current version.
|
||||||
|
return Guice.createInjector(Stage.DEVELOPMENT, new AbstractModule() {
|
||||||
|
@Override
|
||||||
|
protected void configure() {
|
||||||
|
bind(SchemaVersion.class).to(SchemaVersion.C);
|
||||||
|
|
||||||
|
for (Key<?> k : new Key<?>[]{
|
||||||
|
Key.get(PersonIdent.class, GerritPersonIdent.class),
|
||||||
|
Key.get(String.class, AnonymousCowardName.class),
|
||||||
|
}) {
|
||||||
|
rebind(parent, k);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (Class<?> c : new Class<?>[] {
|
||||||
|
AllProjectsName.class,
|
||||||
|
AllUsersCreator.class,
|
||||||
|
GitRepositoryManager.class,
|
||||||
|
SitePaths.class,
|
||||||
|
}) {
|
||||||
|
rebind(parent, Key.get(c));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private <T> void rebind(Injector parent, Key<T> c) {
|
||||||
|
bind(c).toProvider(parent.getProvider(c));
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public void update(final UpdateUI ui) throws OrmException {
|
public void update(final UpdateUI ui) throws OrmException {
|
||||||
|
@@ -21,7 +21,6 @@ import com.google.gwtorm.jdbc.JdbcExecutor;
|
|||||||
import com.google.gwtorm.jdbc.JdbcSchema;
|
import com.google.gwtorm.jdbc.JdbcSchema;
|
||||||
import com.google.gwtorm.server.OrmException;
|
import com.google.gwtorm.server.OrmException;
|
||||||
import com.google.gwtorm.server.StatementExecutor;
|
import com.google.gwtorm.server.StatementExecutor;
|
||||||
import com.google.inject.AbstractModule;
|
|
||||||
import com.google.inject.Provider;
|
import com.google.inject.Provider;
|
||||||
|
|
||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
@@ -34,11 +33,8 @@ public abstract class SchemaVersion {
|
|||||||
/** The current schema version. */
|
/** The current schema version. */
|
||||||
public static final Class<Schema_103> C = Schema_103.class;
|
public static final Class<Schema_103> C = Schema_103.class;
|
||||||
|
|
||||||
public static class Module extends AbstractModule {
|
public static int getBinaryVersion() {
|
||||||
@Override
|
return guessVersion(C);
|
||||||
protected void configure() {
|
|
||||||
bind(SchemaVersion.class).annotatedWith(Current.class).to(C);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private final Provider<? extends SchemaVersion> prior;
|
private final Provider<? extends SchemaVersion> prior;
|
||||||
@@ -49,7 +45,7 @@ public abstract class SchemaVersion {
|
|||||||
this.versionNbr = guessVersion(getClass());
|
this.versionNbr = guessVersion(getClass());
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int guessVersion(Class<?> c) {
|
private static int guessVersion(Class<?> c) {
|
||||||
String n = c.getName();
|
String n = c.getName();
|
||||||
n = n.substring(n.lastIndexOf('_') + 1);
|
n = n.substring(n.lastIndexOf('_') + 1);
|
||||||
while (n.startsWith("0"))
|
while (n.startsWith("0"))
|
||||||
@@ -57,12 +53,6 @@ public abstract class SchemaVersion {
|
|||||||
return Integer.parseInt(n);
|
return Integer.parseInt(n);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected SchemaVersion(final Provider<? extends SchemaVersion> prior,
|
|
||||||
final int versionNbr) {
|
|
||||||
this.prior = prior;
|
|
||||||
this.versionNbr = versionNbr;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** @return the {@link CurrentSchemaVersion#versionNbr} this step targets. */
|
/** @return the {@link CurrentSchemaVersion#versionNbr} this step targets. */
|
||||||
public final int getVersionNbr() {
|
public final int getVersionNbr() {
|
||||||
return versionNbr;
|
return versionNbr;
|
||||||
|
@@ -23,7 +23,6 @@ import com.google.gwtorm.server.OrmException;
|
|||||||
import com.google.gwtorm.server.SchemaFactory;
|
import com.google.gwtorm.server.SchemaFactory;
|
||||||
import com.google.inject.Inject;
|
import com.google.inject.Inject;
|
||||||
import com.google.inject.Module;
|
import com.google.inject.Module;
|
||||||
import com.google.inject.Provider;
|
|
||||||
import com.google.inject.ProvisionException;
|
import com.google.inject.ProvisionException;
|
||||||
|
|
||||||
/** Validates the current schema version. */
|
/** Validates the current schema version. */
|
||||||
@@ -40,16 +39,11 @@ public class SchemaVersionCheck implements LifecycleListener {
|
|||||||
private final SchemaFactory<ReviewDb> schema;
|
private final SchemaFactory<ReviewDb> schema;
|
||||||
private final SitePaths site;
|
private final SitePaths site;
|
||||||
|
|
||||||
@Current
|
|
||||||
private final Provider<SchemaVersion> version;
|
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public SchemaVersionCheck(SchemaFactory<ReviewDb> schemaFactory,
|
public SchemaVersionCheck(SchemaFactory<ReviewDb> schemaFactory,
|
||||||
final SitePaths site,
|
SitePaths site) {
|
||||||
@Current Provider<SchemaVersion> version) {
|
|
||||||
this.schema = schemaFactory;
|
this.schema = schemaFactory;
|
||||||
this.site = site;
|
this.site = site;
|
||||||
this.version = version;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -58,7 +52,7 @@ public class SchemaVersionCheck implements LifecycleListener {
|
|||||||
final ReviewDb db = schema.open();
|
final ReviewDb db = schema.open();
|
||||||
try {
|
try {
|
||||||
final CurrentSchemaVersion currentVer = getSchemaVersion(db);
|
final CurrentSchemaVersion currentVer = getSchemaVersion(db);
|
||||||
final int expectedVer = version.get().getVersionNbr();
|
final int expectedVer = SchemaVersion.getBinaryVersion();
|
||||||
|
|
||||||
if (currentVer == null) {
|
if (currentVer == null) {
|
||||||
throw new ProvisionException("Schema not yet initialized."
|
throw new ProvisionException("Schema not yet initialized."
|
||||||
|
@@ -74,7 +74,6 @@ public class SchemaUpdaterTest {
|
|||||||
protected void configure() {
|
protected void configure() {
|
||||||
bind(new TypeLiteral<SchemaFactory<ReviewDb>>() {}).toInstance(db);
|
bind(new TypeLiteral<SchemaFactory<ReviewDb>>() {}).toInstance(db);
|
||||||
bind(SitePaths.class).toInstance(paths);
|
bind(SitePaths.class).toInstance(paths);
|
||||||
install(new SchemaVersion.Module());
|
|
||||||
|
|
||||||
Config cfg = new Config();
|
Config cfg = new Config();
|
||||||
cfg.setString("user", null, "name", "Gerrit Code Review");
|
cfg.setString("user", null, "name", "Gerrit Code Review");
|
||||||
|
@@ -67,7 +67,6 @@ public class InMemoryDatabase implements SchemaFactory<ReviewDb> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private final SchemaVersion schemaVersion;
|
|
||||||
private final SchemaCreator schemaCreator;
|
private final SchemaCreator schemaCreator;
|
||||||
|
|
||||||
private Connection openHandle;
|
private Connection openHandle;
|
||||||
@@ -75,9 +74,7 @@ public class InMemoryDatabase implements SchemaFactory<ReviewDb> {
|
|||||||
private boolean created;
|
private boolean created;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
InMemoryDatabase(SchemaVersion schemaVersion,
|
InMemoryDatabase(SchemaCreator schemaCreator) throws OrmException {
|
||||||
SchemaCreator schemaCreator) throws OrmException {
|
|
||||||
this.schemaVersion = schemaVersion;
|
|
||||||
this.schemaCreator = schemaCreator;
|
this.schemaCreator = schemaCreator;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@@ -161,6 +158,6 @@ public class InMemoryDatabase implements SchemaFactory<ReviewDb> {
|
|||||||
|
|
||||||
public void assertSchemaVersion() throws OrmException {
|
public void assertSchemaVersion() throws OrmException {
|
||||||
final CurrentSchemaVersion act = getSchemaVersion();
|
final CurrentSchemaVersion act = getSchemaVersion();
|
||||||
assertEquals(schemaVersion.getVersionNbr(), act.versionNbr);
|
assertEquals(SchemaVersion.getBinaryVersion(), act.versionNbr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -48,10 +48,8 @@ import com.google.gerrit.server.index.ChangeSchemas;
|
|||||||
import com.google.gerrit.server.index.IndexModule.IndexType;
|
import com.google.gerrit.server.index.IndexModule.IndexType;
|
||||||
import com.google.gerrit.server.mail.SignedTokenEmailTokenVerifier;
|
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.schema.Current;
|
|
||||||
import com.google.gerrit.server.schema.DataSourceType;
|
import com.google.gerrit.server.schema.DataSourceType;
|
||||||
import com.google.gerrit.server.schema.SchemaCreator;
|
import com.google.gerrit.server.schema.SchemaCreator;
|
||||||
import com.google.gerrit.server.schema.SchemaVersion;
|
|
||||||
import com.google.gerrit.server.securestore.DefaultSecureStore;
|
import com.google.gerrit.server.securestore.DefaultSecureStore;
|
||||||
import com.google.gerrit.server.securestore.SecureStore;
|
import com.google.gerrit.server.securestore.SecureStore;
|
||||||
import com.google.gerrit.server.ssh.NoSshKeyCache;
|
import com.google.gerrit.server.ssh.NoSshKeyCache;
|
||||||
@@ -127,8 +125,6 @@ public class InMemoryModule extends FactoryModule {
|
|||||||
|
|
||||||
bindScope(RequestScoped.class, PerThreadRequestScope.REQUEST);
|
bindScope(RequestScoped.class, PerThreadRequestScope.REQUEST);
|
||||||
|
|
||||||
install(new SchemaVersion.Module());
|
|
||||||
|
|
||||||
bind(File.class).annotatedWith(SitePath.class).toInstance(new File("."));
|
bind(File.class).annotatedWith(SitePath.class).toInstance(new File("."));
|
||||||
bind(Config.class).annotatedWith(GerritServerConfig.class).toInstance(cfg);
|
bind(Config.class).annotatedWith(GerritServerConfig.class).toInstance(cfg);
|
||||||
bind(SocketAddress.class).annotatedWith(RemotePeer.class).toInstance(
|
bind(SocketAddress.class).annotatedWith(RemotePeer.class).toInstance(
|
||||||
@@ -197,9 +193,9 @@ public class InMemoryModule extends FactoryModule {
|
|||||||
|
|
||||||
@Provides
|
@Provides
|
||||||
@Singleton
|
@Singleton
|
||||||
InMemoryDatabase getInMemoryDatabase(@Current SchemaVersion schemaVersion,
|
InMemoryDatabase getInMemoryDatabase(SchemaCreator schemaCreator)
|
||||||
SchemaCreator schemaCreator) throws OrmException {
|
throws OrmException {
|
||||||
return new InMemoryDatabase(schemaVersion, schemaCreator);
|
return new InMemoryDatabase(schemaCreator);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Module luceneIndexModule() {
|
private Module luceneIndexModule() {
|
||||||
|
Reference in New Issue
Block a user