All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.google.gerrit.server.index.IndexModule Maven / Gradle / Ivy

There is a newer version: 3.10.1
Show newest version
// Copyright (C) 2013 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.index;

import static com.google.gerrit.server.git.QueueProvider.QueueType.BATCH;
import static com.google.gerrit.server.git.QueueProvider.QueueType.INTERACTIVE;

import com.google.common.base.Ticker;
import com.google.common.collect.FluentIterable;
import com.google.common.collect.ImmutableCollection;
import com.google.common.collect.ImmutableList;
import com.google.common.util.concurrent.ListeningExecutorService;
import com.google.common.util.concurrent.MoreExecutors;
import com.google.gerrit.extensions.events.LifecycleListener;
import com.google.gerrit.extensions.registration.DynamicSet;
import com.google.gerrit.index.IndexDefinition;
import com.google.gerrit.index.IndexType;
import com.google.gerrit.index.SchemaDefinitions;
import com.google.gerrit.index.project.ProjectIndexCollection;
import com.google.gerrit.index.project.ProjectIndexRewriter;
import com.google.gerrit.index.project.ProjectIndexer;
import com.google.gerrit.index.project.ProjectSchemaDefinitions;
import com.google.gerrit.lifecycle.LifecycleModule;
import com.google.gerrit.server.config.GerritServerConfig;
import com.google.gerrit.server.git.MultiProgressMonitor;
import com.google.gerrit.server.git.WorkQueue;
import com.google.gerrit.server.index.account.AccountIndexCollection;
import com.google.gerrit.server.index.account.AccountIndexDefinition;
import com.google.gerrit.server.index.account.AccountIndexRewriter;
import com.google.gerrit.server.index.account.AccountIndexer;
import com.google.gerrit.server.index.account.AccountIndexerImpl;
import com.google.gerrit.server.index.account.AccountSchemaDefinitions;
import com.google.gerrit.server.index.change.ChangeIndexCollection;
import com.google.gerrit.server.index.change.ChangeIndexDefinition;
import com.google.gerrit.server.index.change.ChangeIndexRewriter;
import com.google.gerrit.server.index.change.ChangeIndexer;
import com.google.gerrit.server.index.change.ChangeSchemaDefinitions;
import com.google.gerrit.server.index.group.GroupIndexCollection;
import com.google.gerrit.server.index.group.GroupIndexDefinition;
import com.google.gerrit.server.index.group.GroupIndexRewriter;
import com.google.gerrit.server.index.group.GroupIndexer;
import com.google.gerrit.server.index.group.GroupIndexerImpl;
import com.google.gerrit.server.index.group.GroupSchemaDefinitions;
import com.google.gerrit.server.index.options.IsFirstInsertForEntry;
import com.google.gerrit.server.index.project.ProjectIndexDefinition;
import com.google.gerrit.server.index.project.ProjectIndexerImpl;
import com.google.inject.Inject;
import com.google.inject.Injector;
import com.google.inject.Key;
import com.google.inject.Provides;
import com.google.inject.ProvisionException;
import com.google.inject.Singleton;
import com.google.inject.multibindings.OptionalBinder;
import java.util.Collection;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import org.eclipse.jgit.lib.Config;

/**
 * Module for non-indexer-specific secondary index setup.
 *
 * 

This module should not be used directly except by specific secondary indexer implementations * (e.g. Lucene). */ public class IndexModule extends LifecycleModule { public static final ImmutableCollection> ALL_SCHEMA_DEFS = ImmutableList.of( AccountSchemaDefinitions.INSTANCE, ChangeSchemaDefinitions.INSTANCE, GroupSchemaDefinitions.INSTANCE, ProjectSchemaDefinitions.INSTANCE); /** Type of secondary index. */ public static IndexType getIndexType(Injector injector) { Config cfg = injector.getInstance(Key.get(Config.class, GerritServerConfig.class)); String configValue = cfg != null ? cfg.getString("index", null, "type") : null; return new IndexType(configValue); } private final int threads; private final ListeningExecutorService interactiveExecutor; private final ListeningExecutorService batchExecutor; private final boolean closeExecutorsOnShutdown; private final boolean slave; public IndexModule(int threads, boolean slave) { this.threads = threads; this.slave = slave; this.interactiveExecutor = null; this.batchExecutor = null; this.closeExecutorsOnShutdown = true; } public IndexModule( ListeningExecutorService interactiveExecutor, ListeningExecutorService batchExecutor) { this.threads = 0; this.interactiveExecutor = interactiveExecutor; this.batchExecutor = batchExecutor; this.closeExecutorsOnShutdown = false; slave = false; } @Override protected void configure() { factory(MultiProgressMonitor.Factory.class); OptionalBinder.newOptionalBinder(binder(), Ticker.class) .setDefault() .toInstance(Ticker.systemTicker()); bind(AccountIndexRewriter.class); bind(AccountIndexCollection.class); listener().to(AccountIndexCollection.class); factory(AccountIndexerImpl.Factory.class); bind(ChangeIndexRewriter.class); bind(ChangeIndexCollection.class); listener().to(ChangeIndexCollection.class); factory(ChangeIndexer.Factory.class); bind(GroupIndexRewriter.class); // GroupIndexCollection is already bound very high up in SchemaModule. listener().to(GroupIndexCollection.class); factory(GroupIndexerImpl.Factory.class); bind(ProjectIndexRewriter.class); bind(ProjectIndexCollection.class); listener().to(ProjectIndexCollection.class); factory(ProjectIndexerImpl.Factory.class); if (closeExecutorsOnShutdown) { // The executors must be shutdown _before_ closing the indexes. // On Gerrit start the LifecycleListeners are invoked in the order in which they are // registered, but on shutdown of Gerrit the order is reversed. This means the // LifecycleListener to shutdown the executors must be registered _after_ the // LifecycleListeners that close the indexes. The closing of the indexes is done by // *IndexCollection which have been registered as LifecycleListener above. The // registration of the ShutdownIndexExecutors LifecycleListener must happen afterwards. listener().to(ShutdownIndexExecutors.class); } DynamicSet.setOf(binder(), OnlineUpgradeListener.class); OptionalBinder.newOptionalBinder(binder(), IsFirstInsertForEntry.class) .setDefault() .toInstance(IsFirstInsertForEntry.NO); } @Provides Collection> getIndexDefinitions( AccountIndexDefinition accounts, ChangeIndexDefinition changes, GroupIndexDefinition groups, ProjectIndexDefinition projects) { if (slave) { // In slave mode, we only have the group index. return ImmutableList.of(groups); } Collection> result = ImmutableList.of(accounts, groups, changes, projects); Set expected = FluentIterable.from(ALL_SCHEMA_DEFS).transform(SchemaDefinitions::getName).toSet(); Set actual = FluentIterable.from(result).transform(IndexDefinition::getName).toSet(); if (!expected.equals(actual)) { throw new ProvisionException( "need index definitions for all schemas: " + expected + " != " + actual); } return result; } @Provides @Singleton AccountIndexer getAccountIndexer( AccountIndexerImpl.Factory factory, AccountIndexCollection indexes) { return factory.create(indexes); } @Provides @Singleton ChangeIndexer getChangeIndexer( @IndexExecutor(INTERACTIVE) ListeningExecutorService executor, ChangeIndexer.Factory factory, ChangeIndexCollection indexes) { // Bind default indexer to interactive executor; callers who need a // different executor can use the factory directly. return factory.create(executor, indexes); } @Provides @Singleton GroupIndexer getGroupIndexer(GroupIndexerImpl.Factory factory, GroupIndexCollection indexes) { return factory.create(indexes); } @Provides @Singleton ProjectIndexer getProjectIndexer( ProjectIndexerImpl.Factory factory, ProjectIndexCollection indexes) { return factory.create(indexes); } @Provides @Singleton @IndexExecutor(INTERACTIVE) ListeningExecutorService getInteractiveIndexExecutor( @GerritServerConfig Config config, WorkQueue workQueue) { if (interactiveExecutor != null) { return interactiveExecutor; } int threads = this.threads; if (threads == 0) { threads = config.getInt( "index", null, "threads", Runtime.getRuntime().availableProcessors() / 2 + 1); } if (threads < 0) { return MoreExecutors.newDirectExecutorService(); } return MoreExecutors.listeningDecorator( workQueue.createQueue(threads, "Index-Interactive", true)); } @Provides @Singleton @IndexExecutor(BATCH) ListeningExecutorService getBatchIndexExecutor( @GerritServerConfig Config config, WorkQueue workQueue) { if (batchExecutor != null) { return batchExecutor; } int threads = this.threads; if (threads == 0) { threads = config.getInt("index", null, "batchThreads", Runtime.getRuntime().availableProcessors()); } if (threads < 0) { return MoreExecutors.newDirectExecutorService(); } return MoreExecutors.listeningDecorator(workQueue.createQueue(threads, "Index-Batch", true)); } @Singleton private static class ShutdownIndexExecutors implements LifecycleListener { private final ListeningExecutorService interactiveExecutor; private final ListeningExecutorService batchExecutor; @Inject ShutdownIndexExecutors( @IndexExecutor(INTERACTIVE) ListeningExecutorService interactiveExecutor, @IndexExecutor(BATCH) ListeningExecutorService batchExecutor) { this.interactiveExecutor = interactiveExecutor; this.batchExecutor = batchExecutor; } @Override public void start() {} @Override public void stop() { MoreExecutors.shutdownAndAwaitTermination( interactiveExecutor, Long.MAX_VALUE, TimeUnit.SECONDS); MoreExecutors.shutdownAndAwaitTermination(batchExecutor, Long.MAX_VALUE, TimeUnit.SECONDS); } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy