Line data Source code
1 : // Copyright (C) 2017 The Android Open Source Project 2 : // 3 : // Licensed under the Apache License, Version 2.0 (the "License"); 4 : // you may not use this file except in compliance with the License. 5 : // You may obtain a copy of the License at 6 : // 7 : // http://www.apache.org/licenses/LICENSE-2.0 8 : // 9 : // Unless required by applicable law or agreed to in writing, software 10 : // distributed under the License is distributed on an "AS IS" BASIS, 11 : // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 : // See the License for the specific language governing permissions and 13 : // limitations under the License. 14 : 15 : package com.google.gerrit.server.index.project; 16 : 17 : import com.google.common.collect.ImmutableSet; 18 : import com.google.common.flogger.FluentLogger; 19 : import com.google.gerrit.common.Nullable; 20 : import com.google.gerrit.entities.Project; 21 : import com.google.gerrit.exceptions.StorageException; 22 : import com.google.gerrit.extensions.events.ProjectIndexedListener; 23 : import com.google.gerrit.index.project.ProjectData; 24 : import com.google.gerrit.index.project.ProjectIndex; 25 : import com.google.gerrit.index.project.ProjectIndexCollection; 26 : import com.google.gerrit.index.project.ProjectIndexer; 27 : import com.google.gerrit.server.logging.Metadata; 28 : import com.google.gerrit.server.logging.TraceContext; 29 : import com.google.gerrit.server.logging.TraceContext.TraceTimer; 30 : import com.google.gerrit.server.plugincontext.PluginSetContext; 31 : import com.google.gerrit.server.project.ProjectCache; 32 : import com.google.gerrit.server.project.ProjectState; 33 : import com.google.inject.assistedinject.Assisted; 34 : import com.google.inject.assistedinject.AssistedInject; 35 : import java.util.Collection; 36 : import java.util.Collections; 37 : import java.util.Optional; 38 : 39 : /** 40 : * Implementation for indexing a Gerrit-managed repository (project). The project will be loaded 41 : * from {@link ProjectCache}. 42 : */ 43 : public class ProjectIndexerImpl implements ProjectIndexer { 44 147 : private static final FluentLogger logger = FluentLogger.forEnclosingClass(); 45 : 46 : public interface Factory { 47 : ProjectIndexerImpl create(ProjectIndexCollection indexes); 48 : 49 : ProjectIndexerImpl create(@Nullable ProjectIndex index); 50 : } 51 : 52 : private final ProjectCache projectCache; 53 : private final PluginSetContext<ProjectIndexedListener> indexedListener; 54 : @Nullable private final ProjectIndexCollection indexes; 55 : @Nullable private final ProjectIndex index; 56 : 57 : @AssistedInject 58 : ProjectIndexerImpl( 59 : ProjectCache projectCache, 60 : PluginSetContext<ProjectIndexedListener> indexedListener, 61 147 : @Assisted ProjectIndexCollection indexes) { 62 147 : this.projectCache = projectCache; 63 147 : this.indexedListener = indexedListener; 64 147 : this.indexes = indexes; 65 147 : this.index = null; 66 147 : } 67 : 68 : @AssistedInject 69 : ProjectIndexerImpl( 70 : ProjectCache projectCache, 71 : PluginSetContext<ProjectIndexedListener> indexedListener, 72 0 : @Assisted @Nullable ProjectIndex index) { 73 0 : this.projectCache = projectCache; 74 0 : this.indexedListener = indexedListener; 75 0 : this.indexes = null; 76 0 : this.index = index; 77 0 : } 78 : 79 : @Override 80 : public void index(Project.NameKey nameKey) { 81 147 : Optional<ProjectState> projectState = projectCache.get(nameKey); 82 147 : if (projectState.isPresent()) { 83 147 : logger.atFine().log("Replace project %s in index", nameKey.get()); 84 147 : ProjectData projectData = projectState.get().toProjectData(); 85 147 : for (ProjectIndex i : getWriteIndexes()) { 86 147 : try (TraceTimer traceTimer = 87 147 : TraceContext.newTimer( 88 : "Replacing project", 89 147 : Metadata.builder() 90 147 : .projectName(nameKey.get()) 91 147 : .indexVersion(i.getSchema().getVersion()) 92 147 : .build())) { 93 147 : i.replace(projectData); 94 1 : } catch (RuntimeException e) { 95 1 : throw new StorageException( 96 1 : String.format( 97 : "Failed to replace project %s in index version %d", 98 1 : nameKey.get(), i.getSchema().getVersion()), 99 : e); 100 147 : } 101 147 : } 102 147 : fireProjectIndexedEvent(nameKey.get()); 103 147 : } else { 104 0 : logger.atFine().log("Delete project %s from index", nameKey.get()); 105 0 : for (ProjectIndex i : getWriteIndexes()) { 106 0 : try (TraceTimer traceTimer = 107 0 : TraceContext.newTimer( 108 : "Deleting project", 109 0 : Metadata.builder() 110 0 : .projectName(nameKey.get()) 111 0 : .indexVersion(i.getSchema().getVersion()) 112 0 : .build())) { 113 0 : i.delete(nameKey); 114 0 : } catch (RuntimeException e) { 115 0 : throw new StorageException( 116 0 : String.format( 117 : "Failed to delete project %s from index version %d", 118 0 : nameKey.get(), i.getSchema().getVersion()), 119 : e); 120 0 : } 121 0 : } 122 : } 123 147 : } 124 : 125 : private void fireProjectIndexedEvent(String name) { 126 147 : indexedListener.runEach(l -> l.onProjectIndexed(name)); 127 147 : } 128 : 129 : private Collection<ProjectIndex> getWriteIndexes() { 130 147 : if (indexes != null) { 131 147 : return indexes.getWriteIndexes(); 132 : } 133 : 134 0 : return index != null ? Collections.singleton(index) : ImmutableSet.of(); 135 : } 136 : }