package org.sonar.server.computation.step;
import org.sonar.api.resources.Qualifiers;
+import org.sonar.api.utils.System2;
+import org.sonar.core.persistence.DbSession;
+import org.sonar.core.persistence.MyBatis;
import org.sonar.server.computation.ComputationContext;
+import org.sonar.server.db.DbClient;
import org.sonar.server.source.index.SourceLineIndexer;
public class IndexSourceLinesStep implements ComputationStep {
+ private final DbClient dbClient;
+ private final System2 system2;
private final SourceLineIndexer indexer;
- public IndexSourceLinesStep(SourceLineIndexer indexer) {
+ public IndexSourceLinesStep(DbClient dbClient, System2 system2, SourceLineIndexer indexer) {
+ this.dbClient = dbClient;
+ this.system2 = system2;
this.indexer = indexer;
}
@Override
public void execute(ComputationContext context) {
+ updateSourceUpdateDate(context.getProject().uuid());
indexer.index();
}
+ // Temporary solution to only index in E/S updated sources from current project
+ // Should be removed when source wil be persisted in compute engine
+ private void updateSourceUpdateDate(String projectUuid){
+ DbSession session = dbClient.openSession(true);
+ try {
+ dbClient.fileSourceDao().updateDateWhenUpdatedDateIsZero(session, projectUuid, system2.now());
+ session.commit();
+ } finally {
+ MyBatis.closeQuietly(session);
+ }
+ }
+
@Override
public String getDescription() {
return "Index source lines";
*/
package org.sonar.server.computation.step;
+import org.elasticsearch.search.SearchHit;
+import org.junit.Before;
+import org.junit.ClassRule;
import org.junit.Test;
+import org.sonar.api.config.Settings;
+import org.sonar.api.resources.Qualifiers;
+import org.sonar.api.utils.System2;
+import org.sonar.batch.protocol.output.BatchReportReader;
+import org.sonar.core.persistence.DbTester;
+import org.sonar.core.source.db.FileSourceDao;
+import org.sonar.server.component.ComponentTesting;
+import org.sonar.server.computation.ComputationContext;
+import org.sonar.server.db.DbClient;
+import org.sonar.server.es.EsTester;
+import org.sonar.server.source.db.FileSourceTesting;
+import org.sonar.server.source.index.SourceLineDoc;
+import org.sonar.server.source.index.SourceLineIndexDefinition;
import org.sonar.server.source.index.SourceLineIndexer;
import java.io.IOException;
+import java.sql.Connection;
+import java.util.Date;
+import java.util.List;
+import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
public class IndexSourceLinesStepTest extends BaseStepTest {
- @Test
- public void supportedProjectQualifiers() throws Exception {
+ @ClassRule
+ public static DbTester dbTester = new DbTester();
+
+ @ClassRule
+ public static EsTester esTester = new EsTester().addDefinitions(new SourceLineIndexDefinition(new Settings()));
+
+ System2 system2;
+
+ DbClient dbClient;
+ @Before
+ public void setUp() throws Exception {
+ dbClient = new DbClient(dbTester.database(), dbTester.myBatis(), new FileSourceDao(null));
+ system2 = mock(System2.class);
}
@Override
protected ComputationStep step() throws IOException {
- return new IndexSourceLinesStep(mock(SourceLineIndexer.class));
+ SourceLineIndexer sourceLineIndexer = new SourceLineIndexer(dbClient, esTester.client());
+ sourceLineIndexer.setEnabled(true);
+ return new IndexSourceLinesStep(dbClient, system2, sourceLineIndexer);
+ }
+
+ @Test
+ public void supported_project_qualifiers() throws Exception {
+ assertThat(step().supportedProjectQualifiers()).containsOnly(Qualifiers.PROJECT);
+ }
+
+ @Test
+ public void update_source_date_on_sources_with_update_at_to_zero() throws Exception {
+ when(system2.now()).thenReturn(150000000002L);
+ dbTester.prepareDbUnit(getClass(), "update_source_date_on_sources_with_update_at_to_zero.xml");
+ Connection connection = dbTester.openConnection();
+ FileSourceTesting.updateDataColumn(connection, "FILE1_UUID", FileSourceTesting.newRandomData(1).build());
+ connection.close();
+
+ step().execute(new ComputationContext(mock(BatchReportReader.class), ComponentTesting.newProjectDto("ABCD")));
+
+ dbTester.assertDbUnit(getClass(), "update_source_date_on_sources_with_update_at_to_zero-result.xml");
+
+ List<SearchHit> docs = esTester.getDocuments(SourceLineIndexDefinition.INDEX, SourceLineIndexDefinition.TYPE);
+ assertThat(docs).hasSize(1);
+ SourceLineDoc doc = new SourceLineDoc(docs.get(0).sourceAsMap());
+ assertThat(doc.projectUuid()).isEqualTo("ABCD");
+ assertThat(doc.fileUuid()).isEqualTo("FILE1_UUID");
+ assertThat(doc.updateDate()).isEqualTo(new Date(system2.now()));
}
}
--- /dev/null
+<dataset>
+
+ <file_sources id="101" project_uuid="ABCD" file_uuid="FILE1_UUID"
+ binary_data="abcde" data_hash="hash" line_hashes="ABC\nDEF\nGHI" src_hash="FILE_HASH"
+ created_at="1500000000000" updated_at="1500000000002"/>
+
+</dataset>
--- /dev/null
+<dataset>
+
+ <file_sources id="101" project_uuid="ABCD" file_uuid="FILE1_UUID"
+ binary_data="abcde" data_hash="hash" line_hashes="ABC\nDEF\nGHI" src_hash="FILE_HASH"
+ created_at="1500000000000" updated_at="0"/>
+
+</dataset>
.setSrcHash(metadata.hash())
.setLineHashes(lineHashesAsMd5Hex(inputFile))
.setCreatedAt(system2.now())
- .setUpdatedAt(system2.now());
+ .setUpdatedAt(0L);
mapper.insert(dto);
session.commit();
} else {
.setLineHashes(lineHashesAsMd5Hex(inputFile));
// Optimization do not change updated at when updating src_hash to avoid indexation by E/S
if (!dataHash.equals(previousDto.getDataHash())) {
- previousDto.setUpdatedAt(system2.now());
+ previousDto.setUpdatedAt(0L);
}
mapper.update(previousDto);
session.commit();
}
}
+ public void updateDateWhenUpdatedDateIsZero(DbSession session, String projectUuid, long updateDate) {
+ session.getMapper(FileSourceMapper.class).updateDateWhenUpdatedDateIsZero(projectUuid, updateDate);
+ }
+
}
package org.sonar.core.source.db;
+import org.apache.ibatis.annotations.Param;
+
import javax.annotation.CheckForNull;
import java.util.List;
void update(FileSourceDto dto);
+ void updateDateWhenUpdatedDateIsZero(@Param("projectUuid") String projectUuid, @Param("date") Long updateDate);
+
@CheckForNull
String selectLineHashes(String fileUuid);
}
</select>
<insert id="insert" parameterType="org.sonar.core.source.db.FileSourceDto" useGeneratedKeys="false">
- insert into file_sources (project_uuid, file_uuid, created_at, updated_at, binary_data, line_hashes, data_hash, src_hash)
- values (#{projectUuid,jdbcType=VARCHAR}, #{fileUuid,jdbcType=VARCHAR}, #{createdAt,jdbcType=BIGINT},
+ INSERT INTO file_sources (project_uuid, file_uuid, created_at, updated_at, binary_data, line_hashes, data_hash, src_hash)
+ VALUES (#{projectUuid,jdbcType=VARCHAR}, #{fileUuid,jdbcType=VARCHAR}, #{createdAt,jdbcType=BIGINT},
#{updatedAt,jdbcType=BIGINT}, #{binaryData,jdbcType=BLOB}, #{lineHashes,jdbcType=CLOB},
#{dataHash,jdbcType=VARCHAR}, #{srcHash,jdbcType=VARCHAR})
</insert>
<update id="update" parameterType="org.sonar.core.source.db.FileSourceDto" useGeneratedKeys="false">
- update file_sources set
+ UPDATE file_sources SET
updated_at = #{updatedAt,jdbcType=BIGINT},
binary_data = #{binaryData,jdbcType=BLOB},
line_hashes = #{lineHashes,jdbcType=CLOB},
data_hash = #{dataHash,jdbcType=VARCHAR},
src_hash = #{srcHash,jdbcType=VARCHAR}
- where id = #{id}
+ WHERE id = #{id}
+ </update>
+
+ <update id="updateDateWhenUpdatedDateIsZero" parameterType="org.sonar.core.source.db.FileSourceDto" useGeneratedKeys="false">
+ UPDATE file_sources SET
+ updated_at = #{date,jdbcType=BIGINT}
+ WHERE project_uuid = #{projectUuid}
+ AND updated_at = 0
</update>
<select id="selectLineHashes" parameterType="string" resultType="String">
checkTable("update", "file_sources", "project_uuid", "file_uuid", "data_hash", "line_hashes", "src_hash", "created_at", "updated_at");
}
+ @Test
+ public void update_date_when_updated_date_is_zero() throws Exception {
+ setupData("update_date_when_updated_date_is_zero");
+
+ dao.updateDateWhenUpdatedDateIsZero(session, "ABCD", 1500000000002L);
+ session.commit();
+
+ checkTable("update_date_when_updated_date_is_zero", "file_sources", "project_uuid", "file_uuid", "data_hash", "line_hashes", "src_hash", "created_at", "updated_at");
+ }
+
private static class ReaderToStringFunction implements Function<Reader, String> {
String result = null;
--- /dev/null
+<dataset>
+
+ <!-- Updated -->
+ <file_sources id="101" project_uuid="ABCD" file_uuid="FILE1_UUID"
+ binary_data="abcde" data_hash="hash" line_hashes="ABC\nDEF\nGHI" src_hash="FILE_HASH"
+ created_at="1500000000000" updated_at="1500000000002"/>
+
+ <!-- Not updated because updated_at is not null -->
+ <file_sources id="102" project_uuid="ABCD" file_uuid="FILE2_UUID"
+ binary_data="abcde" data_hash="hash" line_hashes="ABC\nDEF\nGHI" src_hash="FILE_HASH"
+ created_at="1500000000000" updated_at="1500000000000"/>
+
+ <!-- Not updated because on another project -->
+ <file_sources id="103" project_uuid="BCDE" file_uuid="FILE3_UUID"
+ binary_data="abcde" data_hash="hash" line_hashes="ABC\nDEF\nGHI" src_hash="FILE_HASH"
+ created_at="1500000000000" updated_at="0"/>
+
+</dataset>
--- /dev/null
+<dataset>
+
+ <!-- Only this source should be updated -->
+ <file_sources id="101" project_uuid="ABCD" file_uuid="FILE1_UUID"
+ binary_data="abcde" data_hash="hash" line_hashes="ABC\nDEF\nGHI" src_hash="FILE_HASH"
+ created_at="1500000000000" updated_at="0"/>
+
+ <file_sources id="102" project_uuid="ABCD" file_uuid="FILE2_UUID"
+ binary_data="abcde" data_hash="hash" line_hashes="ABC\nDEF\nGHI" src_hash="FILE_HASH"
+ created_at="1500000000000" updated_at="1500000000000"/>
+
+ <file_sources id="103" project_uuid="BCDE" file_uuid="FILE3_UUID"
+ binary_data="abcde" data_hash="hash" line_hashes="ABC\nDEF\nGHI" src_hash="FILE_HASH"
+ created_at="1500000000000" updated_at="0"/>
+
+</dataset>