@@ -19,11 +19,10 @@ | |||
*/ | |||
package org.sonar.server.computation; | |||
import java.util.concurrent.ScheduledExecutorService; | |||
import org.sonar.server.util.StoppableExecutorService; | |||
import org.sonar.server.util.StoppableScheduledExecutorService; | |||
/** | |||
* The {@link java.util.concurrent.ExecutorService} responsible for running {@link ComputeEngineTask}. | |||
*/ | |||
public interface ComputeEngineProcessingExecutorService extends StoppableExecutorService, ScheduledExecutorService { | |||
public interface ComputeEngineProcessingExecutorService extends StoppableScheduledExecutorService { | |||
} |
@@ -20,14 +20,11 @@ | |||
package org.sonar.server.computation; | |||
import com.google.common.util.concurrent.ThreadFactoryBuilder; | |||
import java.util.concurrent.Callable; | |||
import java.util.concurrent.Executors; | |||
import java.util.concurrent.ScheduledExecutorService; | |||
import java.util.concurrent.ScheduledFuture; | |||
import java.util.concurrent.TimeUnit; | |||
import org.sonar.server.util.AbstractStoppableExecutorService; | |||
import org.sonar.server.util.AbstractStoppableScheduledExecutorServiceImpl; | |||
public class ComputeEngineProcessingExecutorServiceImpl extends AbstractStoppableExecutorService<ScheduledExecutorService> | |||
public class ComputeEngineProcessingExecutorServiceImpl extends AbstractStoppableScheduledExecutorServiceImpl<ScheduledExecutorService> | |||
implements ComputeEngineProcessingExecutorService { | |||
private static final String THREAD_NAME_PREFIX = "ce-processor-"; | |||
@@ -40,23 +37,4 @@ public class ComputeEngineProcessingExecutorServiceImpl extends AbstractStoppabl | |||
.build())); | |||
} | |||
@Override | |||
public ScheduledFuture<?> schedule(Runnable command, long delay, TimeUnit unit) { | |||
return delegate.schedule(command, delay, unit); | |||
} | |||
@Override | |||
public <V> ScheduledFuture<V> schedule(Callable<V> callable, long delay, TimeUnit unit) { | |||
return delegate.schedule(callable, delay, unit); | |||
} | |||
@Override | |||
public ScheduledFuture<?> scheduleAtFixedRate(Runnable command, long initialDelay, long period, TimeUnit unit) { | |||
return delegate.scheduleAtFixedRate(command, initialDelay, period, unit); | |||
} | |||
@Override | |||
public ScheduledFuture<?> scheduleWithFixedDelay(Runnable command, long initialDelay, long delay, TimeUnit unit) { | |||
return delegate.scheduleWithFixedDelay(command, initialDelay, delay, unit); | |||
} | |||
} |
@@ -19,11 +19,10 @@ | |||
*/ | |||
package org.sonar.server.computation; | |||
import java.util.concurrent.ScheduledExecutorService; | |||
import org.sonar.server.util.StoppableExecutorService; | |||
import org.sonar.server.util.StoppableScheduledExecutorService; | |||
/** | |||
* ExecutorService responsible for adding {@link ReportProcessingTask} to {@link ReportQueue} on a regular basis. | |||
*/ | |||
public interface ReportProcessingSchedulerExecutorService extends ScheduledExecutorService, StoppableExecutorService { | |||
public interface ReportProcessingSchedulerExecutorService extends StoppableScheduledExecutorService { | |||
} |
@@ -20,44 +20,21 @@ | |||
package org.sonar.server.computation; | |||
import com.google.common.util.concurrent.ThreadFactoryBuilder; | |||
import java.util.concurrent.Callable; | |||
import java.util.concurrent.Executors; | |||
import java.util.concurrent.ScheduledExecutorService; | |||
import java.util.concurrent.ScheduledFuture; | |||
import java.util.concurrent.TimeUnit; | |||
import org.sonar.server.util.AbstractStoppableExecutorService; | |||
import org.sonar.server.util.AbstractStoppableScheduledExecutorServiceImpl; | |||
public class ReportProcessingSchedulerExecutorServiceImpl extends AbstractStoppableExecutorService<ScheduledExecutorService> | |||
implements ReportProcessingSchedulerExecutorService { | |||
public class ReportProcessingSchedulerExecutorServiceImpl extends AbstractStoppableScheduledExecutorServiceImpl<ScheduledExecutorService> | |||
implements ReportProcessingSchedulerExecutorService { | |||
private static final String THREAD_NAME_PREFIX = "ce-report-scheduler-"; | |||
public ReportProcessingSchedulerExecutorServiceImpl() { | |||
super( | |||
Executors.newSingleThreadScheduledExecutor( | |||
new ThreadFactoryBuilder() | |||
.setNameFormat(THREAD_NAME_PREFIX + "%d") | |||
.setPriority(Thread.MIN_PRIORITY) | |||
.build() | |||
)); | |||
Executors.newSingleThreadScheduledExecutor( | |||
new ThreadFactoryBuilder() | |||
.setNameFormat(THREAD_NAME_PREFIX + "%d") | |||
.setPriority(Thread.MIN_PRIORITY) | |||
.build())); | |||
} | |||
@Override | |||
public ScheduledFuture<?> schedule(Runnable command, long delay, TimeUnit unit) { | |||
return delegate.schedule(command, delay, unit); | |||
} | |||
@Override | |||
public <V> ScheduledFuture<V> schedule(Callable<V> callable, long delay, TimeUnit unit) { | |||
return delegate.schedule(callable, delay, unit); | |||
} | |||
@Override | |||
public ScheduledFuture<?> scheduleAtFixedRate(Runnable command, long initialDelay, long period, TimeUnit unit) { | |||
return delegate.scheduleAtFixedRate(command, initialDelay, period, unit); | |||
} | |||
@Override | |||
public ScheduledFuture<?> scheduleWithFixedDelay(Runnable command, long initialDelay, long delay, TimeUnit unit) { | |||
return delegate.scheduleWithFixedDelay(command, initialDelay, delay, unit); | |||
} | |||
} |
@@ -21,12 +21,8 @@ package org.sonar.server.computation.formula.counter; | |||
import com.google.common.base.Optional; | |||
import org.sonar.server.computation.formula.Counter; | |||
import org.sonar.server.computation.formula.LeafAggregateContext; | |||
public interface SumCounter<T extends Number, COUNTER extends SumCounter<T, COUNTER>> extends Counter<COUNTER> { | |||
void aggregate(COUNTER counter); | |||
void aggregate(LeafAggregateContext context); | |||
Optional<T> getValue(); | |||
} |
@@ -35,7 +35,6 @@ import org.sonar.server.computation.component.DbIdsRepository; | |||
import org.sonar.server.computation.component.DbIdsRepositoryImpl; | |||
import org.sonar.server.computation.component.MutableDbIdsRepository; | |||
import org.sonar.server.computation.component.PathAwareCrawler; | |||
import org.sonar.server.computation.component.PathAwareVisitor; | |||
import org.sonar.server.computation.component.PathAwareVisitorAdapter; | |||
import org.sonar.server.computation.component.TreeRootHolder; | |||
import org.sonar.server.computation.period.Period; | |||
@@ -95,44 +94,49 @@ public class PersistSnapshotsStep implements ComputationStep { | |||
@Override | |||
public void visitProject(Component project, Path<SnapshotDtoHolder> path) { | |||
this.rootId = dbIdsRepository.getComponentId(project); | |||
SnapshotDto snapshot = createSnapshot(project, path, Qualifiers.PROJECT, Scopes.PROJECT, true, true); | |||
SnapshotDto snapshot = createSnapshot(project, path, Qualifiers.PROJECT, Scopes.PROJECT, true); | |||
updateSnapshotPeriods(snapshot); | |||
commonForAnyVisit(project, path, snapshot); | |||
} | |||
@Override | |||
public void visitModule(Component module, Path<SnapshotDtoHolder> path) { | |||
SnapshotDto snapshot = createSnapshot(module, path, Qualifiers.MODULE, Scopes.PROJECT, true, true); | |||
SnapshotDto snapshot = createSnapshot(module, path, Qualifiers.MODULE, Scopes.PROJECT, true); | |||
updateSnapshotPeriods(snapshot); | |||
commonForAnyVisit(module, path, snapshot); | |||
} | |||
@Override | |||
public void visitDirectory(Component directory, Path<SnapshotDtoHolder> path) { | |||
SnapshotDto snapshot = createSnapshot(directory, path, Qualifiers.DIRECTORY, Scopes.DIRECTORY, false, false); | |||
SnapshotDto snapshot = createSnapshot(directory, path, Qualifiers.DIRECTORY, Scopes.DIRECTORY, false); | |||
commonForAnyVisit(directory, path, snapshot); | |||
} | |||
@Override | |||
public void visitFile(Component file, Path<SnapshotDtoHolder> path) { | |||
SnapshotDto snapshot = createSnapshot(file, path, getFileQualifier(file), Scopes.FILE, false, false); | |||
SnapshotDto snapshot = createSnapshot(file, path, getFileQualifier(file), Scopes.FILE, false); | |||
commonForAnyVisit(file, path, snapshot); | |||
} | |||
@Override | |||
public void visitView(Component view, Path<SnapshotDtoHolder> path) { | |||
this.rootId = dbIdsRepository.getComponentId(view); | |||
SnapshotDto snapshot = createSnapshot(view, path, Qualifiers.VIEW, Scopes.PROJECT, false, true); | |||
SnapshotDto snapshot = createSnapshot(view, path, Qualifiers.VIEW, Scopes.PROJECT, false); | |||
updateSnapshotPeriods(snapshot); | |||
commonForAnyVisit(view, path, snapshot); | |||
} | |||
@Override | |||
public void visitSubView(Component subView, Path<SnapshotDtoHolder> path) { | |||
SnapshotDto snapshot = createSnapshot(subView, path, Qualifiers.SUBVIEW, Scopes.PROJECT, false, true); | |||
SnapshotDto snapshot = createSnapshot(subView, path, Qualifiers.SUBVIEW, Scopes.PROJECT, false); | |||
updateSnapshotPeriods(snapshot); | |||
commonForAnyVisit(subView, path, snapshot); | |||
} | |||
@Override | |||
public void visitProjectView(Component projectView, Path<SnapshotDtoHolder> path) { | |||
SnapshotDto snapshot = createSnapshot(projectView, path, Qualifiers.PROJECT, Scopes.FILE, false, true); | |||
SnapshotDto snapshot = createSnapshot(projectView, path, Qualifiers.PROJECT, Scopes.FILE, false); | |||
updateSnapshotPeriods(snapshot); | |||
commonForAnyVisit(projectView, path, snapshot); | |||
} | |||
@@ -144,45 +148,37 @@ public class PersistSnapshotsStep implements ComputationStep { | |||
} | |||
} | |||
private SnapshotDto createSnapshot(Component component, PathAwareVisitor.Path<SnapshotDtoHolder> path, | |||
String qualifier, String scope, boolean setVersion, boolean setPeriods) { | |||
return PersistSnapshotsStep.this.createSnapshot(component, path, rootId, analysisDate, qualifier, scope, setVersion, setPeriods); | |||
private SnapshotDto createSnapshot(Component component, Path<SnapshotDtoHolder> path, | |||
String qualifier, String scope, boolean setVersion) { | |||
long componentId = dbIdsRepository.getComponentId(component); | |||
SnapshotDto snapshotDto = new SnapshotDto() | |||
.setRootProjectId(rootId) | |||
.setVersion(setVersion ? component.getReportAttributes().getVersion() : null) | |||
.setComponentId(componentId) | |||
.setQualifier(qualifier) | |||
.setScope(scope) | |||
.setLast(false) | |||
.setStatus(SnapshotDto.STATUS_UNPROCESSED) | |||
.setCreatedAt(analysisDate) | |||
.setBuildDate(system2.now()); | |||
SnapshotDto parentSnapshot = path.isRoot() ? null : path.parent().getSnapshotDto(); | |||
if (parentSnapshot != null) { | |||
snapshotDto | |||
.setParentId(parentSnapshot.getId()) | |||
.setRootId(parentSnapshot.getRootId() == null ? parentSnapshot.getId() : parentSnapshot.getRootId()) | |||
.setDepth(parentSnapshot.getDepth() + 1) | |||
.setPath(parentSnapshot.getPath() + parentSnapshot.getId() + "."); | |||
} else { | |||
snapshotDto | |||
// On Oracle, the path will be null | |||
.setPath("") | |||
.setDepth(0); | |||
} | |||
return snapshotDto; | |||
} | |||
} | |||
private SnapshotDto createSnapshot(Component component, PathAwareVisitor.Path<SnapshotDtoHolder> path, | |||
long rootId, long analysisDate, String qualifier, String scope, boolean setVersion, boolean setPeriods) { | |||
long componentId = dbIdsRepository.getComponentId(component); | |||
SnapshotDto snapshotDto = new SnapshotDto() | |||
.setRootProjectId(rootId) | |||
.setVersion(setVersion ? component.getReportAttributes().getVersion() : null) | |||
.setComponentId(componentId) | |||
.setQualifier(qualifier) | |||
.setScope(scope) | |||
.setLast(false) | |||
.setStatus(SnapshotDto.STATUS_UNPROCESSED) | |||
.setCreatedAt(analysisDate) | |||
.setBuildDate(system2.now()); | |||
if (setPeriods) { | |||
updateSnapshotPeriods(snapshotDto); | |||
} | |||
SnapshotDto parentSnapshot = path.isRoot() ? null : path.parent().getSnapshotDto(); | |||
if (parentSnapshot != null) { | |||
snapshotDto | |||
.setParentId(parentSnapshot.getId()) | |||
.setRootId(parentSnapshot.getRootId() == null ? parentSnapshot.getId() : parentSnapshot.getRootId()) | |||
.setDepth(parentSnapshot.getDepth() + 1) | |||
.setPath(parentSnapshot.getPath() + parentSnapshot.getId() + "."); | |||
} else { | |||
snapshotDto | |||
// On Oracle, the path will be null | |||
.setPath("") | |||
.setDepth(0); | |||
} | |||
return snapshotDto; | |||
} | |||
private void persist(SnapshotDto snapshotDto, DbSession dbSession) { | |||
dbClient.snapshotDao().insert(dbSession, snapshotDto); | |||
} |
@@ -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.util; | |||
import java.util.concurrent.Callable; | |||
import java.util.concurrent.ScheduledExecutorService; | |||
import java.util.concurrent.ScheduledFuture; | |||
import java.util.concurrent.TimeUnit; | |||
public class AbstractStoppableScheduledExecutorServiceImpl<T extends ScheduledExecutorService> extends AbstractStoppableExecutorService<T> | |||
implements StoppableScheduledExecutorService { | |||
public AbstractStoppableScheduledExecutorServiceImpl(T delegate) { | |||
super(delegate); | |||
} | |||
@Override | |||
public ScheduledFuture<?> schedule(Runnable command, long delay, TimeUnit unit) { | |||
return delegate.schedule(command, delay, unit); | |||
} | |||
@Override | |||
public <V> ScheduledFuture<V> schedule(Callable<V> callable, long delay, TimeUnit unit) { | |||
return delegate.schedule(callable, delay, unit); | |||
} | |||
@Override | |||
public ScheduledFuture<?> scheduleAtFixedRate(Runnable command, long initialDelay, long period, TimeUnit unit) { | |||
return delegate.scheduleAtFixedRate(command, initialDelay, period, unit); | |||
} | |||
@Override | |||
public ScheduledFuture<?> scheduleWithFixedDelay(Runnable command, long initialDelay, long delay, TimeUnit unit) { | |||
return delegate.scheduleWithFixedDelay(command, initialDelay, delay, unit); | |||
} | |||
} |
@@ -0,0 +1,30 @@ | |||
/* | |||
* 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.util; | |||
import java.util.concurrent.ScheduledExecutorService; | |||
/** | |||
* ScheduledExecutorService that exposes a {@code stop} method which can be invoked by Pico container to shutdown | |||
* properly the service. | |||
*/ | |||
public interface StoppableScheduledExecutorService extends ScheduledExecutorService, StoppableExecutorService { | |||
} |