Skip to content

Commit

Permalink
SONAR-6085 Create Views Index
Browse files Browse the repository at this point in the history
  • Loading branch information
julienlancelot committed Jan 27, 2015
1 parent 5221996 commit 0987632
Show file tree
Hide file tree
Showing 23 changed files with 609 additions and 55 deletions.
Expand Up @@ -94,15 +94,15 @@ public ProjectRepositories load(ProjectRepositoryQuery query) {
projectKey = project.key(); projectKey = project.key();
} }


List<ComponentDto> moduleChildren = dbClient.componentDao().findChildrenModulesFromModule(session, query.getModuleKey()); List<ComponentDto> modulesTree = dbClient.componentDao().selectModulesTree(session, module.uuid());
Map<String, String> moduleUuidsByKey = moduleUuidsByKey(module, moduleChildren); Map<String, String> moduleUuidsByKey = moduleUuidsByKey(module, modulesTree);
Map<String, Long> moduleIdsByKey = moduleIdsByKey(module, moduleChildren); Map<String, Long> moduleIdsByKey = moduleIdsByKey(module, modulesTree);


List<PropertyDto> moduleChildrenSettings = dbClient.propertiesDao().findChildrenModuleProperties(query.getModuleKey(), session); List<PropertyDto> modulesTreeSettings = dbClient.propertiesDao().selectModulePropertiesTree(module.uuid(), session);
TreeModuleSettings treeModuleSettings = new TreeModuleSettings(moduleUuidsByKey, moduleIdsByKey, moduleChildren, moduleChildrenSettings, module); TreeModuleSettings treeModuleSettings = new TreeModuleSettings(moduleUuidsByKey, moduleIdsByKey, modulesTree, modulesTreeSettings, module);


addSettingsToChildrenModules(ref, query.getModuleKey(), Maps.<String, String>newHashMap(), treeModuleSettings, hasScanPerm, session); addSettingsToChildrenModules(ref, query.getModuleKey(), Maps.<String, String>newHashMap(), treeModuleSettings, hasScanPerm, session);
addFileData(session, ref, moduleChildren, module.key()); addFileData(session, ref, modulesTree, module.uuid());
} }


addProfiles(ref, projectKey, query.getProfileName(), session); addProfiles(ref, projectKey, query.getProfileName(), session);
Expand Down Expand Up @@ -251,7 +251,7 @@ private void addFileData(DbSession session, ProjectRepositories ref, List<Compon
moduleKeysByUuid.put(module.uuid(), module.key()); moduleKeysByUuid.put(module.uuid(), module.key());
} }


for (FilePathWithHashDto file : dbClient.componentDao().findFilesFromModule(session, moduleKey)) { for (FilePathWithHashDto file : dbClient.componentDao().selectModuleFilesTree(session, moduleKey)) {
FileData fileData = new FileData(file.getSrcHash(), false, null, null, null); FileData fileData = new FileData(file.getSrcHash(), false, null, null, null);
ref.addFileData(moduleKeysByUuid.get(file.getModuleUuid()), file.getPath(), fileData); ref.addFileData(moduleKeysByUuid.get(file.getModuleUuid()), file.getPath(), fileData);
} }
Expand Down
Expand Up @@ -22,6 +22,7 @@


import com.google.common.collect.Lists; import com.google.common.collect.Lists;
import org.sonar.api.ServerComponent; import org.sonar.api.ServerComponent;
import org.sonar.api.resources.Qualifiers;
import org.sonar.api.resources.Scopes; import org.sonar.api.resources.Scopes;
import org.sonar.api.utils.System2; import org.sonar.api.utils.System2;
import org.sonar.core.component.ComponentDto; import org.sonar.core.component.ComponentDto;
Expand All @@ -37,6 +38,7 @@
import java.util.Collection; import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.Map;


import static com.google.common.collect.Lists.newArrayList; import static com.google.common.collect.Lists.newArrayList;


Expand Down Expand Up @@ -94,12 +96,12 @@ public List<ComponentDto> findSubProjectsByComponentUuids(DbSession session, Col
return mapper(session).findSubProjectsByComponentUuids(keys); return mapper(session).findSubProjectsByComponentUuids(keys);
} }


public List<ComponentDto> findChildrenModulesFromModule(DbSession session, String moduleKey) { public List<ComponentDto> selectModulesTree(DbSession session, String rootComponentUuid) {
return mapper(session).findChildrenModulesFromModule(moduleKey, Scopes.PROJECT); return mapper(session).selectModulesTree(rootComponentUuid, Scopes.PROJECT);
} }


public List<FilePathWithHashDto> findFilesFromModule(DbSession session, String moduleKey) { public List<FilePathWithHashDto> selectModuleFilesTree(DbSession session, String rootComponentUuid) {
return mapper(session).findFilesFromModule(moduleKey, Scopes.FILE); return mapper(session).selectModuleFilesTree(rootComponentUuid, Scopes.FILE);
} }


public List<ComponentDto> getByUuids(DbSession session, Collection<String> uuids) { public List<ComponentDto> getByUuids(DbSession session, Collection<String> uuids) {
Expand Down Expand Up @@ -140,4 +142,12 @@ protected void doDeleteByKey(DbSession session, String key) {
public List<String> findProjectUuids(DbSession session) { public List<String> findProjectUuids(DbSession session) {
return mapper(session).findProjectUuids(); return mapper(session).findProjectUuids();
} }

public List<Map<String, String>> selectAllViewsAndSubViews(DbSession session) {
return mapper(session).selectAllViewsAndSubViews(Qualifiers.VIEW, Qualifiers.SUBVIEW);
}

public List<String> selectProjectsFromView(DbSession session, String projectViewUuid, String viewUuid) {
return mapper(session).selectProjectsFromView(projectViewUuid, "%." + viewUuid + ".%", Qualifiers.SUBVIEW);
}
} }
Expand Up @@ -192,6 +192,8 @@
import org.sonar.server.user.ws.UserPropertiesWs; import org.sonar.server.user.ws.UserPropertiesWs;
import org.sonar.server.user.ws.UsersWs; import org.sonar.server.user.ws.UsersWs;
import org.sonar.server.util.*; import org.sonar.server.util.*;
import org.sonar.server.view.index.ViewIndexDefinition;
import org.sonar.server.view.index.ViewIndexer;
import org.sonar.server.ws.ListingWs; import org.sonar.server.ws.ListingWs;
import org.sonar.server.ws.WebServiceEngine; import org.sonar.server.ws.WebServiceEngine;


Expand Down Expand Up @@ -509,6 +511,10 @@ void startLevel4Components(ComponentContainer pico) {
pico.addSingleton(EventsWs.class); pico.addSingleton(EventsWs.class);
pico.addSingleton(ComponentCleanerService.class); pico.addSingleton(ComponentCleanerService.class);


// views
pico.addSingleton(ViewIndexDefinition.class);
pico.addSingleton(ViewIndexer.class);

// issues // issues
pico.addSingleton(IssueIndexDefinition.class); pico.addSingleton(IssueIndexDefinition.class);
pico.addSingleton(IssueIndexer.class); pico.addSingleton(IssueIndexer.class);
Expand Down
Expand Up @@ -31,6 +31,7 @@
import org.sonar.server.rule.index.RuleIndex; import org.sonar.server.rule.index.RuleIndex;
import org.sonar.server.source.index.SourceLineIndexer; import org.sonar.server.source.index.SourceLineIndexer;
import org.sonar.server.user.index.UserIndexer; import org.sonar.server.user.index.UserIndexer;
import org.sonar.server.view.index.ViewIndexer;


import java.util.Date; import java.util.Date;


Expand All @@ -44,15 +45,17 @@ public class IndexSynchronizer {
private final IssueAuthorizationIndexer issueAuthorizationIndexer; private final IssueAuthorizationIndexer issueAuthorizationIndexer;
private final IssueIndexer issueIndexer; private final IssueIndexer issueIndexer;
private final UserIndexer userIndexer; private final UserIndexer userIndexer;
private final ViewIndexer viewIndexer;


public IndexSynchronizer(DbClient db, IndexClient index, SourceLineIndexer sourceLineIndexer, public IndexSynchronizer(DbClient db, IndexClient index, SourceLineIndexer sourceLineIndexer,
IssueAuthorizationIndexer issueAuthorizationIndexer, IssueIndexer issueIndexer, UserIndexer userIndexer) { IssueAuthorizationIndexer issueAuthorizationIndexer, IssueIndexer issueIndexer, UserIndexer userIndexer, ViewIndexer viewIndexer) {
this.db = db; this.db = db;
this.index = index; this.index = index;
this.sourceLineIndexer = sourceLineIndexer; this.sourceLineIndexer = sourceLineIndexer;
this.issueAuthorizationIndexer = issueAuthorizationIndexer; this.issueAuthorizationIndexer = issueAuthorizationIndexer;
this.issueIndexer = issueIndexer; this.issueIndexer = issueIndexer;
this.userIndexer = userIndexer; this.userIndexer = userIndexer;
this.viewIndexer = viewIndexer;
} }


public void execute() { public void execute() {
Expand All @@ -75,6 +78,9 @@ public void execute() {


LOG.info("Index users"); LOG.info("Index users");
userIndexer.index(); userIndexer.index();

LOG.info("Index views");
viewIndexer.index();
} }


void synchronize(DbSession session, Dao dao, Index index) { void synchronize(DbSession session, Dao dao, Index index) {
Expand Down
Expand Up @@ -80,7 +80,7 @@ private UserResultSetIterator(PreparedStatement stmt) throws SQLException {


@Override @Override
protected UserDoc read(ResultSet rs) throws SQLException { protected UserDoc read(ResultSet rs) throws SQLException {
UserDoc doc = new UserDoc(Maps.<String, Object>newHashMapWithExpectedSize(30)); UserDoc doc = new UserDoc(Maps.<String, Object>newHashMapWithExpectedSize(7));


String login = rs.getString(1); String login = rs.getString(1);


Expand Down
@@ -0,0 +1,52 @@
/*
* SonarQube, open source software quality management tool.
* Copyright (C) 2008-2014 SonarSource
* mailto:contact AT sonarsource DOT com
*
* SonarQube is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* SonarQube is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/

package org.sonar.server.view.index;

import org.sonar.server.search.BaseDoc;

import java.util.List;
import java.util.Map;

public class ViewDoc extends BaseDoc {

public ViewDoc(Map<String, Object> fields) {
super(fields);
}

public String uuid() {
return getField(ViewIndexDefinition.FIELD_UUID);
}

public List<String> projects() {
return getField(ViewIndexDefinition.FIELD_PROJECTS);
}

public ViewDoc setUuid(String s) {
setField(ViewIndexDefinition.FIELD_UUID, s);
return this;
}

public ViewDoc setProjects(List<String> s) {
setField(ViewIndexDefinition.FIELD_PROJECTS, s);
return this;
}

}
@@ -0,0 +1,66 @@
/*
* SonarQube, open source software quality management tool.
* Copyright (C) 2008-2014 SonarSource
* mailto:contact AT sonarsource DOT com
*
* SonarQube is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* SonarQube is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/

package org.sonar.server.view.index;

import com.google.common.collect.ImmutableMap;
import org.elasticsearch.cluster.metadata.IndexMetaData;
import org.sonar.api.config.Settings;
import org.sonar.process.ProcessConstants;
import org.sonar.server.es.IndexDefinition;
import org.sonar.server.es.NewIndex;

/**
* Definition of ES index "views", including settings and fields.
*/
public class ViewIndexDefinition implements IndexDefinition {

public static final String INDEX = "views";

public static final String TYPE_VIEW = "view";

public static final String FIELD_UUID = "uuid";
public static final String FIELD_PROJECTS = "projects";

private final Settings settings;

public ViewIndexDefinition(Settings settings) {
this.settings = settings;
}

@Override
public void define(IndexDefinitionContext context) {
NewIndex index = context.create(INDEX);

// shards
boolean clusterMode = settings.getBoolean(ProcessConstants.CLUSTER_ACTIVATE);
if (clusterMode) {
index.getSettings().put(IndexMetaData.SETTING_NUMBER_OF_SHARDS, 4);
index.getSettings().put(IndexMetaData.SETTING_NUMBER_OF_REPLICAS, 1);
// else keep defaults (one shard)
}

// type "view"
NewIndex.NewIndexType mapping = index.createType(TYPE_VIEW);
mapping.setAttribute("_id", ImmutableMap.of("path", FIELD_UUID));
mapping.stringFieldBuilder(FIELD_UUID).build();
mapping.stringFieldBuilder(FIELD_PROJECTS).build();
}
}
@@ -0,0 +1,102 @@
/*
* SonarQube, open source software quality management tool.
* Copyright (C) 2008-2014 SonarSource
* mailto:contact AT sonarsource DOT com
*
* SonarQube is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* SonarQube is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/

package org.sonar.server.view.index;

import com.google.common.collect.Maps;
import org.elasticsearch.action.update.UpdateRequest;
import org.sonar.core.component.ComponentDto;
import org.sonar.core.persistence.DbSession;
import org.sonar.server.db.DbClient;
import org.sonar.server.es.BaseIndexer;
import org.sonar.server.es.BulkIndexer;
import org.sonar.server.es.EsClient;

import java.util.List;
import java.util.Map;

import static com.google.common.collect.Maps.newHashMap;

public class ViewIndexer extends BaseIndexer {

private final DbClient dbClient;
private final EsClient esClient;

public ViewIndexer(DbClient dbClient, EsClient esClient) {
super(esClient, 300, ViewIndexDefinition.INDEX, ViewIndexDefinition.TYPE_VIEW);
this.dbClient = dbClient;
this.esClient = esClient;
}

@Override
protected long doIndex(long lastUpdatedAt) {
// Index only if index is empty
long count = esClient.prepareCount(ViewIndexDefinition.INDEX).setTypes(ViewIndexDefinition.TYPE_VIEW).get().getCount();
if (count == 0) {
DbSession dbSession = dbClient.openSession(false);
try {
Map<String, String> viewAndProjectViewUuidMap = newHashMap();
for (Map<String, String> viewsMap : dbClient.componentDao().selectAllViewsAndSubViews(dbSession)) {
viewAndProjectViewUuidMap.put(viewsMap.get("uuid"), viewsMap.get("projectUuid"));
}
index(dbSession, viewAndProjectViewUuidMap);
} finally {
dbSession.close();
}
}
return 0L;
}

public void index(String rootViewUuid) {
DbSession dbSession = dbClient.openSession(false);
try {
Map<String, String> viewAndProjectViewUuidMap = newHashMap();
for (ComponentDto viewOrSubView : dbClient.componentDao().selectModulesTree(dbSession, rootViewUuid)) {
viewAndProjectViewUuidMap.put(viewOrSubView.uuid(), viewOrSubView.projectUuid());
}
index(dbSession, viewAndProjectViewUuidMap);
} finally {
dbSession.close();
}
}

private void index(DbSession dbSession, Map<String, String> viewAndProjectViewUuidMap) {
final BulkIndexer bulk = new BulkIndexer(esClient, ViewIndexDefinition.INDEX);
bulk.start();
for (Map.Entry<String, String> entry : viewAndProjectViewUuidMap.entrySet()) {
doIndex(dbSession, bulk, entry.getKey(), entry.getValue());
}
bulk.stop();
}

private void doIndex(DbSession dbSession, BulkIndexer bulk, String uuid, String projectUuid) {
List<String> projects = dbClient.componentDao().selectProjectsFromView(dbSession, projectUuid, uuid);
bulk.add(newUpsertRequest(new ViewDoc(Maps.<String, Object>newHashMap())
.setUuid(uuid)
.setProjects(projects)));
}

private UpdateRequest newUpsertRequest(ViewDoc doc) {
return new UpdateRequest(ViewIndexDefinition.INDEX, ViewIndexDefinition.TYPE_VIEW, doc.uuid())
.doc(doc.getFields())
.upsert(doc.getFields());
}

}
@@ -0,0 +1,25 @@
/*
* SonarQube, open source software quality management tool.
* Copyright (C) 2008-2014 SonarSource
* mailto:contact AT sonarsource DOT com
*
* SonarQube is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* SonarQube is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/

@ParametersAreNonnullByDefault
package org.sonar.server.view.index;

import javax.annotation.ParametersAreNonnullByDefault;

0 comments on commit 0987632

Please sign in to comment.