+++ /dev/null
-/*
- * 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.computation;
-
-public interface CeProcessingScheduler {
-
- void startScheduling();
-
-}
+++ /dev/null
-/*
- * 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.computation;
-
-import org.sonar.server.util.StoppableScheduledExecutorService;
-
-/**
- * The {@link java.util.concurrent.ExecutorService} responsible for running {@link CeWorkerRunnable}.
- */
-public interface CeProcessingSchedulerExecutorService extends StoppableScheduledExecutorService {
-}
+++ /dev/null
-/*
- * 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.computation;
-
-import com.google.common.util.concurrent.ThreadFactoryBuilder;
-import java.util.concurrent.Executors;
-import java.util.concurrent.ScheduledExecutorService;
-import org.sonar.server.util.AbstractStoppableScheduledExecutorServiceImpl;
-
-public class CeProcessingSchedulerExecutorServiceImpl extends AbstractStoppableScheduledExecutorServiceImpl<ScheduledExecutorService>
- implements CeProcessingSchedulerExecutorService {
- private static final String THREAD_NAME_PREFIX = "ce-processor-";
-
- public CeProcessingSchedulerExecutorServiceImpl() {
- super(
- Executors.newSingleThreadScheduledExecutor(
- new ThreadFactoryBuilder()
- .setNameFormat(THREAD_NAME_PREFIX + "%d")
- .setPriority(Thread.MIN_PRIORITY)
- .build()));
- }
-
-}
+++ /dev/null
-/*
- * 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.computation;
-
-import java.util.concurrent.TimeUnit;
-import org.sonar.server.computation.log.CeLogging;
-
-public class CeProcessingSchedulerImpl implements CeProcessingScheduler {
- private final CeProcessingSchedulerExecutorService executorService;
- private final CeQueue ceQueue;
- private final ReportTaskProcessor reportTaskProcessor;
- private final CeLogging ceLogging;
-
- private final long delayBetweenTasks;
- private final long delayForFirstStart;
- private final TimeUnit timeUnit;
-
- public CeProcessingSchedulerImpl(CeProcessingSchedulerExecutorService processingExecutorService, CeQueue ceQueue, ReportTaskProcessor reportTaskProcessor, CeLogging ceLogging) {
- this.executorService = processingExecutorService;
- this.ceQueue = ceQueue;
- this.reportTaskProcessor = reportTaskProcessor;
- this.ceLogging = ceLogging;
-
- this.delayBetweenTasks = 10;
- this.delayForFirstStart = 0;
- this.timeUnit = TimeUnit.SECONDS;
- }
-
- @Override
- public void startScheduling() {
- executorService.scheduleAtFixedRate(new CeWorkerRunnable(ceQueue, reportTaskProcessor, ceLogging), delayForFirstStart, delayBetweenTasks, timeUnit);
- }
-
-}
+++ /dev/null
-/*
- * 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.computation;
-
-import com.google.common.base.Optional;
-import org.sonar.db.ce.CeActivityDto;
-
-/**
- * Queue of pending Compute Engine tasks. Both producer and consumer actions
- * are implemented.
- * <p>
- * This class is decoupled from the regular task type {@link org.sonar.db.ce.CeTaskTypes#REPORT}.
- * </p>
- */
-public interface CeQueue {
- /**
- * Build an instance of {@link CeTaskSubmit} required for {@link #submit(CeTaskSubmit)}. It allows
- * to enforce that task ids are generated by the queue. It's used also for having access
- * to the id before submitting the task to the queue.
- */
- CeTaskSubmit.Builder prepareSubmit();
-
- /**
- * Submits a task to the queue. The task is processed asynchronously.
- * If submits are paused (see {@link #isSubmitPaused()}, then an
- * unchecked exception is thrown.
- */
- CeTask submit(CeTaskSubmit submission);
-
- /**
- * Peek the oldest task in status {@link org.sonar.db.ce.CeQueueDto.Status#PENDING}.
- * The task status is changed to {@link org.sonar.db.ce.CeQueueDto.Status#IN_PROGRESS}.
- * Does not return anything if the queue is paused (see {@link #isPeekPaused()}.
- *
- * <p>Only a single task can be peeked by project.</p>
- *
- * <p>An unchecked exception may be thrown on technical errors (db connection, ...).</p>
- */
- Optional<CeTask> peek();
-
- /**
- * Cancels a task in status {@link org.sonar.db.ce.CeQueueDto.Status#PENDING}. An unchecked
- * exception is thrown if the status is not {@link org.sonar.db.ce.CeQueueDto.Status#PENDING}.
- * The method does nothing and returns {@code false} if the task does not exist.
- *
- * @return true if the task exists and is successfully canceled.
- */
- boolean cancel(String taskUuid);
-
- /**
- * Removes all the tasks from the queue, whatever their status. They are marked
- * as {@link org.sonar.db.ce.CeActivityDto.Status#CANCELED} in past activity.
- * This method can NOT be called when workers are being executed, as in progress
- * tasks can't be killed.
- *
- * @return the number of canceled tasks
- */
- int clear();
-
- /**
- * Similar as {@link #clear()}, except that the tasks with status
- * {@link org.sonar.db.ce.CeQueueDto.Status#IN_PROGRESS} are ignored. This method
- * can be called at runtime, even if workers are being executed.
- *
- * @return the number of canceled tasks
- */
- int cancelAll();
-
- /**
- * Removes a task from the queue and registers it to past activities. This method
- * is called by Compute Engine workers when task is processed.
- *
- * <p>An unchecked exception is thrown if the task does not exist in the queue.</p>
- */
- void remove(CeTask task, CeActivityDto.Status status);
-
- void pauseSubmit();
-
- void resumeSubmit();
-
- boolean isSubmitPaused();
-
- void pausePeek();
-
- void resumePeek();
-
- boolean isPeekPaused();
-}
+++ /dev/null
-/*
- * 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.computation;
-
-import java.util.HashSet;
-import java.util.Set;
-import org.sonar.api.platform.ServerUpgradeStatus;
-import org.sonar.api.server.ServerSide;
-import org.sonar.api.utils.log.Logger;
-import org.sonar.api.utils.log.Loggers;
-import org.sonar.db.DbClient;
-import org.sonar.db.DbSession;
-import org.sonar.db.ce.CeQueueDto;
-import org.sonar.db.ce.CeTaskTypes;
-
-/**
- * Cleans-up the Compute Engine queue and resets the JMX counters.
- * CE workers must not be started before execution of this class.
- */
-@ServerSide
-public class CeQueueCleaner {
-
- private static final Logger LOGGER = Loggers.get(CeQueueCleaner.class);
-
- private final DbClient dbClient;
- private final ServerUpgradeStatus serverUpgradeStatus;
- private final ReportFiles reportFiles;
- private final CeQueueImpl queue;
-
- public CeQueueCleaner(DbClient dbClient, ServerUpgradeStatus serverUpgradeStatus, ReportFiles reportFiles, CeQueueImpl queue) {
- this.dbClient = dbClient;
- this.serverUpgradeStatus = serverUpgradeStatus;
- this.reportFiles = reportFiles;
- this.queue = queue;
- }
-
- public void clean(DbSession dbSession) {
- if (serverUpgradeStatus.isUpgraded()) {
- cleanOnUpgrade();
- } else {
- verifyConsistency(dbSession);
- }
- }
-
- private void cleanOnUpgrade() {
- // we assume that pending tasks are not compatible with the new version
- // and can't be processed
- LOGGER.info("Cancel all pending tasks (due to upgrade)");
- queue.clear();
- }
-
- private void verifyConsistency(DbSession dbSession) {
- // server is not being upgraded
- dbClient.ceQueueDao().resetAllToPendingStatus(dbSession);
- dbSession.commit();
-
- // verify that the report files are available for the tasks in queue
- Set<String> uuidsInQueue = new HashSet<>();
- for (CeQueueDto queueDto : dbClient.ceQueueDao().selectAllInAscOrder(dbSession)) {
- uuidsInQueue.add(queueDto.getUuid());
- if (CeTaskTypes.REPORT.equals(queueDto.getTaskType()) && !reportFiles.fileForUuid(queueDto.getUuid()).exists()) {
- // the report is not available on file system
- queue.cancel(dbSession, queueDto);
- }
- }
-
- // clean-up filesystem
- for (String uuid : reportFiles.listUuids()) {
- if (!uuidsInQueue.contains(uuid)) {
- reportFiles.deleteIfExists(uuid);
- }
- }
- }
-}
+++ /dev/null
-/*
- * 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.computation;
-
-import com.google.common.base.Optional;
-import java.util.concurrent.atomic.AtomicBoolean;
-import org.sonar.api.server.ServerSide;
-import org.sonar.api.utils.System2;
-import org.sonar.core.util.UuidFactory;
-import org.sonar.db.DbClient;
-import org.sonar.db.DbSession;
-import org.sonar.db.ce.CeActivityDto;
-import org.sonar.db.ce.CeQueueDto;
-import org.sonar.db.component.ComponentDto;
-import org.sonar.server.computation.monitoring.CEQueueStatus;
-
-import static com.google.common.base.Preconditions.checkState;
-import static java.lang.String.format;
-
-@ServerSide
-public class CeQueueImpl implements CeQueue {
-
- private final System2 system2;
- private final DbClient dbClient;
- private final UuidFactory uuidFactory;
- private final CEQueueStatus queueStatus;
- private final CeQueueListener[] listeners;
-
- // state
- private AtomicBoolean submitPaused = new AtomicBoolean(false);
- private AtomicBoolean peekPaused = new AtomicBoolean(false);
-
- public CeQueueImpl(System2 system2, DbClient dbClient, UuidFactory uuidFactory,
- CEQueueStatus queueStatus, CeQueueListener[] listeners) {
- this.system2 = system2;
- this.dbClient = dbClient;
- this.uuidFactory = uuidFactory;
- this.queueStatus = queueStatus;
- this.listeners = listeners;
- }
-
- @Override
- public CeTaskSubmit.Builder prepareSubmit() {
- return new CeTaskSubmit.Builder(uuidFactory.create());
- }
-
- @Override
- public CeTask submit(CeTaskSubmit submission) {
- checkState(!submitPaused.get(), "Compute Engine does not currently accept new tasks");
-
- DbSession dbSession = dbClient.openSession(false);
- try {
- CeQueueDto dto = new CeQueueDto();
- dto.setUuid(submission.getUuid());
- dto.setTaskType(submission.getType());
- dto.setComponentUuid(submission.getComponentUuid());
- dto.setStatus(CeQueueDto.Status.PENDING);
- dto.setSubmitterLogin(submission.getSubmitterLogin());
- dto.setStartedAt(null);
- dbClient.ceQueueDao().insert(dbSession, dto);
- CeTask task = loadTask(dbSession, dto);
- dbSession.commit();
- queueStatus.addReceived();
- return task;
-
- } finally {
- dbClient.closeSession(dbSession);
- }
- }
-
- @Override
- public Optional<CeTask> peek() {
- if (peekPaused.get()) {
- return Optional.absent();
- }
- DbSession dbSession = dbClient.openSession(false);
- try {
- Optional<CeQueueDto> dto = dbClient.ceQueueDao().peek(dbSession);
- CeTask task = null;
- if (dto.isPresent()) {
- task = loadTask(dbSession, dto.get());
- queueStatus.addInProgress();
- }
- return Optional.fromNullable(task);
-
- } finally {
- dbClient.closeSession(dbSession);
- }
- }
-
- private CeTask loadTask(DbSession dbSession, CeQueueDto dto) {
- CeTask.Builder builder = new CeTask.Builder();
- builder.setUuid(dto.getUuid());
- builder.setType(dto.getTaskType());
- builder.setSubmitterLogin(dto.getSubmitterLogin());
- String componentUuid = dto.getComponentUuid();
- if (componentUuid != null) {
- builder.setComponentUuid(componentUuid);
- Optional<ComponentDto> component = dbClient.componentDao().selectByUuid(dbSession, componentUuid);
- if (component.isPresent()) {
- builder.setComponentKey(component.get().getKey());
- builder.setComponentName(component.get().name());
- }
- }
- return builder.build();
- }
-
- @Override
- public boolean cancel(String taskUuid) {
- DbSession dbSession = dbClient.openSession(false);
- try {
- Optional<CeQueueDto> queueDto = dbClient.ceQueueDao().selectByUuid(dbSession, taskUuid);
- if (queueDto.isPresent()) {
- checkState(CeQueueDto.Status.PENDING.equals(queueDto.get().getStatus()), "Task is in progress and can't be canceled [uuid=%s]", taskUuid);
- cancel(dbSession, queueDto.get());
- return true;
- }
- return false;
- } finally {
- dbClient.closeSession(dbSession);
- }
- }
-
- void cancel(DbSession dbSession, CeQueueDto q) {
- CeTask task = loadTask(dbSession, q);
- CeActivityDto activityDto = new CeActivityDto(q);
- activityDto.setStatus(CeActivityDto.Status.CANCELED);
- remove(dbSession, task, q, activityDto);
- }
-
- @Override
- public int clear() {
- return cancelAll(true);
- }
-
- @Override
- public int cancelAll() {
- return cancelAll(false);
- }
-
- private int cancelAll(boolean includeInProgress) {
- int count = 0;
- DbSession dbSession = dbClient.openSession(false);
- try {
- for (CeQueueDto queueDto : dbClient.ceQueueDao().selectAllInAscOrder(dbSession)) {
- if (includeInProgress || !queueDto.getStatus().equals(CeQueueDto.Status.IN_PROGRESS)) {
- cancel(dbSession, queueDto);
- count++;
- }
- }
- return count;
- } finally {
- dbClient.closeSession(dbSession);
- }
- }
-
- @Override
- public void remove(CeTask task, CeActivityDto.Status status) {
- DbSession dbSession = dbClient.openSession(false);
- try {
- Optional<CeQueueDto> queueDto = dbClient.ceQueueDao().selectByUuid(dbSession, task.getUuid());
- if (!queueDto.isPresent()) {
- throw new IllegalStateException(format("Task does not exist anymore: %s", task));
- }
- CeActivityDto activityDto = new CeActivityDto(queueDto.get());
- activityDto.setStatus(status);
- updateQueueStatus(status, activityDto);
- remove(dbSession, task, queueDto.get(), activityDto);
-
- } finally {
- dbClient.closeSession(dbSession);
- }
- }
-
- private void updateQueueStatus(CeActivityDto.Status status, CeActivityDto activityDto) {
- Long startedAt = activityDto.getStartedAt();
- if (startedAt == null) {
- return;
- }
- activityDto.setFinishedAt(system2.now());
- long executionTime = activityDto.getFinishedAt() - startedAt;
- activityDto.setExecutionTimeMs(executionTime);
- if (status == CeActivityDto.Status.SUCCESS) {
- queueStatus.addSuccess(executionTime);
- } else {
- queueStatus.addError(executionTime);
- }
- }
-
- private void remove(DbSession dbSession, CeTask task, CeQueueDto queueDto, CeActivityDto activityDto) {
- dbClient.ceActivityDao().insert(dbSession, activityDto);
- dbClient.ceQueueDao().deleteByUuid(dbSession, queueDto.getUuid());
- dbSession.commit();
- for (CeQueueListener listener : listeners) {
- listener.onRemoved(task, activityDto.getStatus());
- }
- }
-
- @Override
- public void pauseSubmit() {
- this.submitPaused.set(true);
- }
-
- @Override
- public void resumeSubmit() {
- this.submitPaused.set(false);
- }
-
- @Override
- public boolean isSubmitPaused() {
- return submitPaused.get();
- }
-
- @Override
- public void pausePeek() {
- this.peekPaused.set(true);
- }
-
- @Override
- public void resumePeek() {
- this.peekPaused.set(false);
- }
-
- @Override
- public boolean isPeekPaused() {
- return peekPaused.get();
- }
-}
+++ /dev/null
-/*
- * 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.computation;
-
-import org.picocontainer.Startable;
-import org.sonar.api.server.ServerSide;
-import org.sonar.db.DbClient;
-import org.sonar.db.DbSession;
-import org.sonar.server.computation.monitoring.CEQueueStatus;
-
-/**
- * Cleans-up the queue, initializes JMX counters then schedule
- * the execution of workers. That allows to not prevent workers
- * from peeking the queue before it's ready.
- */
-@ServerSide
-public class CeQueueInitializer implements Startable {
-
- private final DbClient dbClient;
- private final CEQueueStatus queueStatus;
- private final CeQueueCleaner cleaner;
- private final CeProcessingScheduler scheduler;
-
- public CeQueueInitializer(DbClient dbClient, CEQueueStatus queueStatus, CeQueueCleaner cleaner, CeProcessingScheduler scheduler) {
- this.dbClient = dbClient;
- this.queueStatus = queueStatus;
- this.cleaner = cleaner;
- this.scheduler = scheduler;
- }
-
- @Override
- public void start() {
- DbSession dbSession = dbClient.openSession(false);
- try {
- initJmxCounters(dbSession);
- cleaner.clean(dbSession);
- scheduler.startScheduling();
-
- } finally {
- dbClient.closeSession(dbSession);
- }
- }
-
- @Override
- public void stop() {
- // nothing to do
- }
-
- private void initJmxCounters(DbSession dbSession) {
- queueStatus.initPendingCount(dbClient.ceQueueDao().countAll(dbSession));
- }
-}
+++ /dev/null
-/*
- * 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.computation;
-
-import org.sonar.db.ce.CeActivityDto;
-
-public interface CeQueueListener {
-
- void onRemoved(CeTask task, CeActivityDto.Status status);
-
-}
+++ /dev/null
-/*
- * 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.computation;
-
-import com.google.common.base.Objects;
-import javax.annotation.CheckForNull;
-import javax.annotation.Nullable;
-import javax.annotation.concurrent.Immutable;
-
-import static com.google.common.base.Strings.emptyToNull;
-import static java.util.Objects.requireNonNull;
-
-@Immutable
-public class CeTask {
-
- private final String type;
- private final String uuid;
- private final String componentUuid;
- private final String componentKey;
- private final String componentName;
- private final String submitterLogin;
-
- private CeTask(Builder builder) {
- this.uuid = requireNonNull(emptyToNull(builder.uuid));
- this.type = requireNonNull(emptyToNull(builder.type));
- this.componentUuid = emptyToNull(builder.componentUuid);
- this.componentKey = emptyToNull(builder.componentKey);
- this.componentName = emptyToNull(builder.componentName);
- this.submitterLogin = emptyToNull(builder.submitterLogin);
- }
-
- public String getUuid() {
- return uuid;
- }
-
- public String getType() {
- return type;
- }
-
- @CheckForNull
- public String getComponentUuid() {
- return componentUuid;
- }
-
- @CheckForNull
- public String getComponentKey() {
- return componentKey;
- }
-
- @CheckForNull
- public String getComponentName() {
- return componentName;
- }
-
- @CheckForNull
- public String getSubmitterLogin() {
- return submitterLogin;
- }
-
- @Override
- public String toString() {
- return Objects.toStringHelper(this)
- .add("componentUuid", componentUuid)
- .add("uuid", uuid)
- .add("type", type)
- .add("submitterLogin", submitterLogin)
- .toString();
- }
-
- @Override
- public boolean equals(@Nullable Object o) {
- if (this == o) {
- return true;
- }
- if (o == null || getClass() != o.getClass()) {
- return false;
- }
- CeTask ceTask = (CeTask) o;
- return uuid.equals(ceTask.uuid);
- }
-
- @Override
- public int hashCode() {
- return uuid.hashCode();
- }
-
- public static final class Builder {
- private String uuid;
- private String type;
- private String componentUuid;
- private String componentKey;
- private String componentName;
- private String submitterLogin;
-
- public Builder setUuid(String uuid) {
- this.uuid = uuid;
- return this;
- }
-
- public Builder setType(String type) {
- this.type = type;
- return this;
- }
-
- public Builder setComponentUuid(String componentUuid) {
- this.componentUuid = componentUuid;
- return this;
- }
-
- public Builder setComponentKey(@Nullable String s) {
- this.componentKey = s;
- return this;
- }
-
- public Builder setComponentName(@Nullable String s) {
- this.componentName = s;
- return this;
- }
-
- public Builder setSubmitterLogin(@Nullable String s) {
- this.submitterLogin = s;
- return this;
- }
-
- public CeTask build() {
- return new CeTask(this);
- }
- }
-}
+++ /dev/null
-/*
- * 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.computation;
-
-import java.util.Objects;
-import javax.annotation.CheckForNull;
-import javax.annotation.Nullable;
-import javax.annotation.concurrent.Immutable;
-
-import static com.google.common.base.Strings.emptyToNull;
-
-@Immutable
-public final class CeTaskSubmit {
-
- private final String uuid;
- private final String type;
- private final String componentUuid;
- private final String submitterLogin;
-
- private CeTaskSubmit(Builder builder) {
- this.uuid = Objects.requireNonNull(emptyToNull(builder.uuid));
- this.type = Objects.requireNonNull(emptyToNull(builder.type));
- this.componentUuid = emptyToNull(builder.componentUuid);
- this.submitterLogin = emptyToNull(builder.submitterLogin);
- }
-
- public String getType() {
- return type;
- }
-
- public String getUuid() {
- return uuid;
- }
-
- @CheckForNull
- public String getComponentUuid() {
- return componentUuid;
- }
-
- @CheckForNull
- public String getSubmitterLogin() {
- return submitterLogin;
- }
-
- public static final class Builder {
- private final String uuid;
- private String type;
- private String componentUuid;
- private String submitterLogin;
-
- Builder(String uuid) {
- this.uuid = uuid;
- }
-
- public String getUuid() {
- return uuid;
- }
-
- public Builder setType(String s) {
- this.type = s;
- return this;
- }
-
- public Builder setComponentUuid(@Nullable String s) {
- this.componentUuid = s;
- return this;
- }
-
- public Builder setSubmitterLogin(@Nullable String s) {
- this.submitterLogin = s;
- return this;
- }
-
- public CeTaskSubmit build() {
- return new CeTaskSubmit(this);
- }
- }
-}
+++ /dev/null
-/*
- * 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.computation;
-
-import com.google.common.base.Optional;
-import org.sonar.api.utils.log.Logger;
-import org.sonar.api.utils.log.Loggers;
-import org.sonar.core.util.logs.Profiler;
-import org.sonar.db.ce.CeActivityDto;
-import org.sonar.server.computation.log.CeLogging;
-
-import static java.lang.String.format;
-
-class CeWorkerRunnable implements Runnable {
-
- private static final Logger LOG = Loggers.get(CeWorkerRunnable.class);
-
- private final CeQueue queue;
- private final ReportTaskProcessor reportTaskProcessor;
- private final CeLogging ceLogging;
-
- public CeWorkerRunnable(CeQueue queue, ReportTaskProcessor reportTaskProcessor, CeLogging ceLogging) {
- this.queue = queue;
- this.reportTaskProcessor = reportTaskProcessor;
- this.ceLogging = ceLogging;
- }
-
- @Override
- public void run() {
- Optional<CeTask> ceTask = tryAndFindTaskToExecute();
- if (!ceTask.isPresent()) {
- return;
- }
-
- executeTask(ceTask.get());
- }
-
- private Optional<CeTask> tryAndFindTaskToExecute() {
- try {
- return queue.peek();
- } catch (Exception e) {
- LOG.error("Failed to pop the queue of analysis reports", e);
- }
- return Optional.absent();
- }
-
- private void executeTask(CeTask task) {
- ceLogging.initForTask(task);
- Profiler profiler = Profiler.create(LOG).startInfo(format("Analysis of project %s (report %s)", task.getComponentKey(), task.getUuid()));
- try {
- // TODO delegate the message to the related task processor, according to task type
- reportTaskProcessor.process(task);
- queue.remove(task, CeActivityDto.Status.SUCCESS);
- } catch (Throwable e) {
- LOG.error(format("Failed to process task %s", task.getUuid()), e);
- queue.remove(task, CeActivityDto.Status.FAILED);
- } finally {
- profiler.stopInfo(String.format("Total thread execution of project %s (report %s)", task.getComponentUuid(), task.getUuid()));
- ceLogging.clearForTask();
- }
- }
-}
+++ /dev/null
-/*
- * 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.computation;
-
-import org.sonar.db.ce.CeActivityDto;
-
-public class CleanReportQueueListener implements CeQueueListener {
-
- private final ReportFiles reportFiles;
-
- public CleanReportQueueListener(ReportFiles reportFiles) {
- this.reportFiles = reportFiles;
- }
-
- @Override
- public void onRemoved(CeTask task, CeActivityDto.Status status) {
- reportFiles.deleteIfExists(task.getUuid());
- }
-}
import org.sonar.core.platform.Module;
import org.sonar.server.computation.container.ContainerFactoryImpl;
+import org.sonar.server.computation.queue.CeProcessingSchedulerExecutorServiceImpl;
+import org.sonar.server.computation.queue.CeProcessingSchedulerImpl;
+import org.sonar.server.computation.queue.report.ReportTaskProcessor;
public class ComputeEngineProcessingModule extends Module {
@Override
+++ /dev/null
-/*
- * 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.computation;
-
-import java.io.InputStream;
-import javax.annotation.Nullable;
-import org.apache.commons.lang.StringUtils;
-import org.sonar.api.resources.Qualifiers;
-import org.sonar.api.server.ServerSide;
-import org.sonar.core.component.ComponentKeys;
-import org.sonar.core.permission.GlobalPermissions;
-import org.sonar.db.ce.CeTaskTypes;
-import org.sonar.db.component.ComponentDto;
-import org.sonar.server.component.ComponentService;
-import org.sonar.server.component.NewComponent;
-import org.sonar.server.permission.PermissionService;
-import org.sonar.server.user.UserSession;
-
-@ServerSide
-public class ReportSubmitter {
-
- private final CeQueue queue;
- private final UserSession userSession;
- private final ReportFiles reportFiles;
- private final ComponentService componentService;
- private final PermissionService permissionService;
-
- public ReportSubmitter(CeQueue queue, UserSession userSession, ReportFiles reportFiles,
- ComponentService componentService, PermissionService permissionService) {
- this.queue = queue;
- this.userSession = userSession;
- this.reportFiles = reportFiles;
- this.componentService = componentService;
- this.permissionService = permissionService;
- }
-
- public CeTask submit(String projectKey, @Nullable String projectBranch, @Nullable String projectName, InputStream reportInput) {
- userSession.checkGlobalPermission(GlobalPermissions.SCAN_EXECUTION);
-
- String effectiveProjectKey = ComponentKeys.createKey(projectKey, projectBranch);
- ComponentDto project = componentService.getNullableByKey(effectiveProjectKey);
- if (project == null) {
- // the project does not exist -> requires to provision it
- NewComponent newProject = new NewComponent(projectKey, StringUtils.defaultIfBlank(projectName, projectKey));
- newProject.setBranch(projectBranch);
- newProject.setQualifier(Qualifiers.PROJECT);
- // no need to verify the permission "provisioning" as it's already handled by componentService
- project = componentService.create(newProject);
- permissionService.applyDefaultPermissionTemplate(project.getKey());
- }
-
- // the report file must be saved before submitting the task
- CeTaskSubmit.Builder submit = queue.prepareSubmit();
- reportFiles.save(submit.getUuid(), reportInput);
-
- submit.setType(CeTaskTypes.REPORT);
- submit.setComponentUuid(project.uuid());
- submit.setSubmitterLogin(userSession.getLogin());
- return queue.submit(submit.build());
- }
-}
+++ /dev/null
-/*
- * 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.computation;
-
-import org.sonar.core.platform.ComponentContainer;
-import org.sonar.server.computation.container.ComputeEngineContainer;
-import org.sonar.server.computation.container.ContainerFactory;
-
-public class ReportTaskProcessor {
-
- private final ContainerFactory containerFactory;
- private final ComponentContainer serverContainer;
-
- public ReportTaskProcessor(ContainerFactory containerFactory, ComponentContainer serverContainer) {
- this.containerFactory = containerFactory;
- this.serverContainer = serverContainer;
- }
-
- public void process(CeTask task) {
- ComputeEngineContainer ceContainer = containerFactory.create(serverContainer, task);
- try {
- ceContainer.getComponentByType(ComputationStepExecutor.class).execute();
- } finally {
- ceContainer.cleanup();
- }
- }
-}
package org.sonar.server.computation.batch;
import java.io.File;
+import org.sonar.server.computation.queue.CeTask;
public interface BatchReportDirectoryHolder {
/**
- * The File of the directory where the Batch report files for the current {@link org.sonar.server.computation.CeTask} are stored.
+ * The File of the directory where the Batch report files for the current {@link CeTask} are stored.
*
* @throws IllegalStateException if the holder is empty (ie. there is no directory yet)
*/
import org.sonar.core.platform.ComponentContainer;
import org.sonar.core.platform.ContainerPopulator;
+import org.sonar.server.computation.queue.CeTask;
/**
- * The Compute Engine container. Created for a specific parent {@link ComponentContainer} and a specific {@link org.sonar.server.computation.CeTask}.
+ * The Compute Engine container. Created for a specific parent {@link ComponentContainer} and a specific {@link CeTask}.
*/
public interface ComputeEngineContainer extends ContainerPopulator.Container {
package org.sonar.server.computation.container;
import org.sonar.core.platform.ComponentContainer;
-import org.sonar.server.computation.CeTask;
+import org.sonar.server.computation.queue.CeTask;
/**
* Compute
package org.sonar.server.computation.container;
import org.sonar.core.platform.ComponentContainer;
-import org.sonar.server.computation.CeTask;
+import org.sonar.server.computation.queue.CeTask;
public class ContainerFactoryImpl implements ContainerFactory {
@Override
import java.util.List;
import org.sonar.core.issue.tracking.Tracker;
import org.sonar.core.platform.ContainerPopulator;
-import org.sonar.server.computation.CeTask;
+import org.sonar.server.computation.queue.CeTask;
import org.sonar.server.computation.ComputationStepExecutor;
import org.sonar.server.computation.ComputationTempFolderProvider;
import org.sonar.server.computation.analysis.ReportAnalysisMetadataHolder;
import ch.qos.logback.core.sift.AppenderFactory;
import com.google.common.annotations.VisibleForTesting;
import java.io.File;
-import org.sonar.server.computation.CeTask;
+import org.sonar.server.computation.queue.CeTask;
import static java.lang.String.format;
/**
* @param context
* @param discriminatingValue path of log file relative to the directory data/ce/logs
- * @see CeLogging#initForTask(CeTask)
+ * @see CeLogging#initForTask(CeTask)
*/
@Override
public FileAppender<E> buildAppender(Context context, String discriminatingValue) {
import org.sonar.api.config.Settings;
import org.sonar.process.ProcessProperties;
import org.sonar.process.Props;
-import org.sonar.server.computation.CeTask;
+import org.sonar.server.computation.queue.CeTask;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.collect.FluentIterable.from;
import javax.annotation.Nullable;
import org.sonar.db.ce.CeActivityDto;
import org.sonar.db.ce.CeQueueDto;
-import org.sonar.server.computation.CeTask;
+import org.sonar.server.computation.queue.CeTask;
import static java.lang.String.format;
package org.sonar.server.computation.monitoring;
import java.util.LinkedHashMap;
-import org.sonar.server.computation.CeQueue;
+import org.sonar.server.computation.queue.CeQueue;
import org.sonar.server.platform.monitoring.BaseMonitorMBean;
public class ComputeEngineQueueMonitor extends BaseMonitorMBean implements ComputeEngineQueueMonitorMBean {
--- /dev/null
+/*
+ * 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.computation.queue;
+
+public interface CeProcessingScheduler {
+
+ void startScheduling();
+
+}
--- /dev/null
+/*
+ * 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.computation.queue;
+
+import org.sonar.server.util.StoppableScheduledExecutorService;
+
+/**
+ * The {@link java.util.concurrent.ExecutorService} responsible for running {@link CeWorkerRunnable}.
+ */
+public interface CeProcessingSchedulerExecutorService extends StoppableScheduledExecutorService {
+}
--- /dev/null
+/*
+ * 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.computation.queue;
+
+import com.google.common.util.concurrent.ThreadFactoryBuilder;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ScheduledExecutorService;
+import org.sonar.server.util.AbstractStoppableScheduledExecutorServiceImpl;
+
+public class CeProcessingSchedulerExecutorServiceImpl extends AbstractStoppableScheduledExecutorServiceImpl<ScheduledExecutorService>
+ implements CeProcessingSchedulerExecutorService {
+ private static final String THREAD_NAME_PREFIX = "ce-processor-";
+
+ public CeProcessingSchedulerExecutorServiceImpl() {
+ super(
+ Executors.newSingleThreadScheduledExecutor(
+ new ThreadFactoryBuilder()
+ .setNameFormat(THREAD_NAME_PREFIX + "%d")
+ .setPriority(Thread.MIN_PRIORITY)
+ .build()));
+ }
+
+}
--- /dev/null
+/*
+ * 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.computation.queue;
+
+import java.util.concurrent.TimeUnit;
+import org.sonar.server.computation.queue.report.ReportTaskProcessor;
+import org.sonar.server.computation.log.CeLogging;
+
+public class CeProcessingSchedulerImpl implements CeProcessingScheduler {
+ private final CeProcessingSchedulerExecutorService executorService;
+ private final CeQueue ceQueue;
+ private final ReportTaskProcessor reportTaskProcessor;
+ private final CeLogging ceLogging;
+
+ private final long delayBetweenTasks;
+ private final long delayForFirstStart;
+ private final TimeUnit timeUnit;
+
+ public CeProcessingSchedulerImpl(CeProcessingSchedulerExecutorService processingExecutorService, CeQueue ceQueue, ReportTaskProcessor reportTaskProcessor, CeLogging ceLogging) {
+ this.executorService = processingExecutorService;
+ this.ceQueue = ceQueue;
+ this.reportTaskProcessor = reportTaskProcessor;
+ this.ceLogging = ceLogging;
+
+ this.delayBetweenTasks = 10;
+ this.delayForFirstStart = 0;
+ this.timeUnit = TimeUnit.SECONDS;
+ }
+
+ @Override
+ public void startScheduling() {
+ executorService.scheduleAtFixedRate(new CeWorkerRunnable(ceQueue, reportTaskProcessor, ceLogging), delayForFirstStart, delayBetweenTasks, timeUnit);
+ }
+
+}
--- /dev/null
+/*
+ * 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.computation.queue;
+
+import com.google.common.base.Optional;
+import org.sonar.db.ce.CeActivityDto;
+
+/**
+ * Queue of pending Compute Engine tasks. Both producer and consumer actions
+ * are implemented.
+ * <p>
+ * This class is decoupled from the regular task type {@link org.sonar.db.ce.CeTaskTypes#REPORT}.
+ * </p>
+ */
+public interface CeQueue {
+ /**
+ * Build an instance of {@link CeTaskSubmit} required for {@link #submit(CeTaskSubmit)}. It allows
+ * to enforce that task ids are generated by the queue. It's used also for having access
+ * to the id before submitting the task to the queue.
+ */
+ CeTaskSubmit.Builder prepareSubmit();
+
+ /**
+ * Submits a task to the queue. The task is processed asynchronously.
+ * If submits are paused (see {@link #isSubmitPaused()}, then an
+ * unchecked exception is thrown.
+ */
+ CeTask submit(CeTaskSubmit submission);
+
+ /**
+ * Peek the oldest task in status {@link org.sonar.db.ce.CeQueueDto.Status#PENDING}.
+ * The task status is changed to {@link org.sonar.db.ce.CeQueueDto.Status#IN_PROGRESS}.
+ * Does not return anything if the queue is paused (see {@link #isPeekPaused()}.
+ *
+ * <p>Only a single task can be peeked by project.</p>
+ *
+ * <p>An unchecked exception may be thrown on technical errors (db connection, ...).</p>
+ */
+ Optional<CeTask> peek();
+
+ /**
+ * Cancels a task in status {@link org.sonar.db.ce.CeQueueDto.Status#PENDING}. An unchecked
+ * exception is thrown if the status is not {@link org.sonar.db.ce.CeQueueDto.Status#PENDING}.
+ * The method does nothing and returns {@code false} if the task does not exist.
+ *
+ * @return true if the task exists and is successfully canceled.
+ */
+ boolean cancel(String taskUuid);
+
+ /**
+ * Removes all the tasks from the queue, whatever their status. They are marked
+ * as {@link org.sonar.db.ce.CeActivityDto.Status#CANCELED} in past activity.
+ * This method can NOT be called when workers are being executed, as in progress
+ * tasks can't be killed.
+ *
+ * @return the number of canceled tasks
+ */
+ int clear();
+
+ /**
+ * Similar as {@link #clear()}, except that the tasks with status
+ * {@link org.sonar.db.ce.CeQueueDto.Status#IN_PROGRESS} are ignored. This method
+ * can be called at runtime, even if workers are being executed.
+ *
+ * @return the number of canceled tasks
+ */
+ int cancelAll();
+
+ /**
+ * Removes a task from the queue and registers it to past activities. This method
+ * is called by Compute Engine workers when task is processed.
+ *
+ * <p>An unchecked exception is thrown if the task does not exist in the queue.</p>
+ */
+ void remove(CeTask task, CeActivityDto.Status status);
+
+ void pauseSubmit();
+
+ void resumeSubmit();
+
+ boolean isSubmitPaused();
+
+ void pausePeek();
+
+ void resumePeek();
+
+ boolean isPeekPaused();
+}
--- /dev/null
+/*
+ * 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.computation.queue;
+
+import java.util.HashSet;
+import java.util.Set;
+import org.sonar.api.platform.ServerUpgradeStatus;
+import org.sonar.api.server.ServerSide;
+import org.sonar.api.utils.log.Logger;
+import org.sonar.api.utils.log.Loggers;
+import org.sonar.db.DbClient;
+import org.sonar.db.DbSession;
+import org.sonar.db.ce.CeQueueDto;
+import org.sonar.db.ce.CeTaskTypes;
+import org.sonar.server.computation.ReportFiles;
+
+/**
+ * Cleans-up the Compute Engine queue and resets the JMX counters.
+ * CE workers must not be started before execution of this class.
+ */
+@ServerSide
+public class CeQueueCleaner {
+
+ private static final Logger LOGGER = Loggers.get(CeQueueCleaner.class);
+
+ private final DbClient dbClient;
+ private final ServerUpgradeStatus serverUpgradeStatus;
+ private final ReportFiles reportFiles;
+ private final CeQueueImpl queue;
+
+ public CeQueueCleaner(DbClient dbClient, ServerUpgradeStatus serverUpgradeStatus, ReportFiles reportFiles, CeQueueImpl queue) {
+ this.dbClient = dbClient;
+ this.serverUpgradeStatus = serverUpgradeStatus;
+ this.reportFiles = reportFiles;
+ this.queue = queue;
+ }
+
+ public void clean(DbSession dbSession) {
+ if (serverUpgradeStatus.isUpgraded()) {
+ cleanOnUpgrade();
+ } else {
+ verifyConsistency(dbSession);
+ }
+ }
+
+ private void cleanOnUpgrade() {
+ // we assume that pending tasks are not compatible with the new version
+ // and can't be processed
+ LOGGER.info("Cancel all pending tasks (due to upgrade)");
+ queue.clear();
+ }
+
+ private void verifyConsistency(DbSession dbSession) {
+ // server is not being upgraded
+ dbClient.ceQueueDao().resetAllToPendingStatus(dbSession);
+ dbSession.commit();
+
+ // verify that the report files are available for the tasks in queue
+ Set<String> uuidsInQueue = new HashSet<>();
+ for (CeQueueDto queueDto : dbClient.ceQueueDao().selectAllInAscOrder(dbSession)) {
+ uuidsInQueue.add(queueDto.getUuid());
+ if (CeTaskTypes.REPORT.equals(queueDto.getTaskType()) && !reportFiles.fileForUuid(queueDto.getUuid()).exists()) {
+ // the report is not available on file system
+ queue.cancel(dbSession, queueDto);
+ }
+ }
+
+ // clean-up filesystem
+ for (String uuid : reportFiles.listUuids()) {
+ if (!uuidsInQueue.contains(uuid)) {
+ reportFiles.deleteIfExists(uuid);
+ }
+ }
+ }
+}
--- /dev/null
+/*
+ * 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.computation.queue;
+
+import com.google.common.base.Optional;
+import java.util.concurrent.atomic.AtomicBoolean;
+import org.sonar.api.server.ServerSide;
+import org.sonar.api.utils.System2;
+import org.sonar.core.util.UuidFactory;
+import org.sonar.db.DbClient;
+import org.sonar.db.DbSession;
+import org.sonar.db.ce.CeActivityDto;
+import org.sonar.db.ce.CeQueueDto;
+import org.sonar.db.component.ComponentDto;
+import org.sonar.server.computation.monitoring.CEQueueStatus;
+
+import static com.google.common.base.Preconditions.checkState;
+import static java.lang.String.format;
+
+@ServerSide
+public class CeQueueImpl implements CeQueue {
+
+ private final System2 system2;
+ private final DbClient dbClient;
+ private final UuidFactory uuidFactory;
+ private final CEQueueStatus queueStatus;
+ private final CeQueueListener[] listeners;
+
+ // state
+ private AtomicBoolean submitPaused = new AtomicBoolean(false);
+ private AtomicBoolean peekPaused = new AtomicBoolean(false);
+
+ public CeQueueImpl(System2 system2, DbClient dbClient, UuidFactory uuidFactory,
+ CEQueueStatus queueStatus, CeQueueListener[] listeners) {
+ this.system2 = system2;
+ this.dbClient = dbClient;
+ this.uuidFactory = uuidFactory;
+ this.queueStatus = queueStatus;
+ this.listeners = listeners;
+ }
+
+ @Override
+ public CeTaskSubmit.Builder prepareSubmit() {
+ return new CeTaskSubmit.Builder(uuidFactory.create());
+ }
+
+ @Override
+ public CeTask submit(CeTaskSubmit submission) {
+ checkState(!submitPaused.get(), "Compute Engine does not currently accept new tasks");
+
+ DbSession dbSession = dbClient.openSession(false);
+ try {
+ CeQueueDto dto = new CeQueueDto();
+ dto.setUuid(submission.getUuid());
+ dto.setTaskType(submission.getType());
+ dto.setComponentUuid(submission.getComponentUuid());
+ dto.setStatus(CeQueueDto.Status.PENDING);
+ dto.setSubmitterLogin(submission.getSubmitterLogin());
+ dto.setStartedAt(null);
+ dbClient.ceQueueDao().insert(dbSession, dto);
+ CeTask task = loadTask(dbSession, dto);
+ dbSession.commit();
+ queueStatus.addReceived();
+ return task;
+
+ } finally {
+ dbClient.closeSession(dbSession);
+ }
+ }
+
+ @Override
+ public Optional<CeTask> peek() {
+ if (peekPaused.get()) {
+ return Optional.absent();
+ }
+ DbSession dbSession = dbClient.openSession(false);
+ try {
+ Optional<CeQueueDto> dto = dbClient.ceQueueDao().peek(dbSession);
+ CeTask task = null;
+ if (dto.isPresent()) {
+ task = loadTask(dbSession, dto.get());
+ queueStatus.addInProgress();
+ }
+ return Optional.fromNullable(task);
+
+ } finally {
+ dbClient.closeSession(dbSession);
+ }
+ }
+
+ private CeTask loadTask(DbSession dbSession, CeQueueDto dto) {
+ CeTask.Builder builder = new CeTask.Builder();
+ builder.setUuid(dto.getUuid());
+ builder.setType(dto.getTaskType());
+ builder.setSubmitterLogin(dto.getSubmitterLogin());
+ String componentUuid = dto.getComponentUuid();
+ if (componentUuid != null) {
+ builder.setComponentUuid(componentUuid);
+ Optional<ComponentDto> component = dbClient.componentDao().selectByUuid(dbSession, componentUuid);
+ if (component.isPresent()) {
+ builder.setComponentKey(component.get().getKey());
+ builder.setComponentName(component.get().name());
+ }
+ }
+ return builder.build();
+ }
+
+ @Override
+ public boolean cancel(String taskUuid) {
+ DbSession dbSession = dbClient.openSession(false);
+ try {
+ Optional<CeQueueDto> queueDto = dbClient.ceQueueDao().selectByUuid(dbSession, taskUuid);
+ if (queueDto.isPresent()) {
+ checkState(CeQueueDto.Status.PENDING.equals(queueDto.get().getStatus()), "Task is in progress and can't be canceled [uuid=%s]", taskUuid);
+ cancel(dbSession, queueDto.get());
+ return true;
+ }
+ return false;
+ } finally {
+ dbClient.closeSession(dbSession);
+ }
+ }
+
+ void cancel(DbSession dbSession, CeQueueDto q) {
+ CeTask task = loadTask(dbSession, q);
+ CeActivityDto activityDto = new CeActivityDto(q);
+ activityDto.setStatus(CeActivityDto.Status.CANCELED);
+ remove(dbSession, task, q, activityDto);
+ }
+
+ @Override
+ public int clear() {
+ return cancelAll(true);
+ }
+
+ @Override
+ public int cancelAll() {
+ return cancelAll(false);
+ }
+
+ private int cancelAll(boolean includeInProgress) {
+ int count = 0;
+ DbSession dbSession = dbClient.openSession(false);
+ try {
+ for (CeQueueDto queueDto : dbClient.ceQueueDao().selectAllInAscOrder(dbSession)) {
+ if (includeInProgress || !queueDto.getStatus().equals(CeQueueDto.Status.IN_PROGRESS)) {
+ cancel(dbSession, queueDto);
+ count++;
+ }
+ }
+ return count;
+ } finally {
+ dbClient.closeSession(dbSession);
+ }
+ }
+
+ @Override
+ public void remove(CeTask task, CeActivityDto.Status status) {
+ DbSession dbSession = dbClient.openSession(false);
+ try {
+ Optional<CeQueueDto> queueDto = dbClient.ceQueueDao().selectByUuid(dbSession, task.getUuid());
+ if (!queueDto.isPresent()) {
+ throw new IllegalStateException(format("Task does not exist anymore: %s", task));
+ }
+ CeActivityDto activityDto = new CeActivityDto(queueDto.get());
+ activityDto.setStatus(status);
+ updateQueueStatus(status, activityDto);
+ remove(dbSession, task, queueDto.get(), activityDto);
+
+ } finally {
+ dbClient.closeSession(dbSession);
+ }
+ }
+
+ private void updateQueueStatus(CeActivityDto.Status status, CeActivityDto activityDto) {
+ Long startedAt = activityDto.getStartedAt();
+ if (startedAt == null) {
+ return;
+ }
+ activityDto.setFinishedAt(system2.now());
+ long executionTime = activityDto.getFinishedAt() - startedAt;
+ activityDto.setExecutionTimeMs(executionTime);
+ if (status == CeActivityDto.Status.SUCCESS) {
+ queueStatus.addSuccess(executionTime);
+ } else {
+ queueStatus.addError(executionTime);
+ }
+ }
+
+ private void remove(DbSession dbSession, CeTask task, CeQueueDto queueDto, CeActivityDto activityDto) {
+ dbClient.ceActivityDao().insert(dbSession, activityDto);
+ dbClient.ceQueueDao().deleteByUuid(dbSession, queueDto.getUuid());
+ dbSession.commit();
+ for (CeQueueListener listener : listeners) {
+ listener.onRemoved(task, activityDto.getStatus());
+ }
+ }
+
+ @Override
+ public void pauseSubmit() {
+ this.submitPaused.set(true);
+ }
+
+ @Override
+ public void resumeSubmit() {
+ this.submitPaused.set(false);
+ }
+
+ @Override
+ public boolean isSubmitPaused() {
+ return submitPaused.get();
+ }
+
+ @Override
+ public void pausePeek() {
+ this.peekPaused.set(true);
+ }
+
+ @Override
+ public void resumePeek() {
+ this.peekPaused.set(false);
+ }
+
+ @Override
+ public boolean isPeekPaused() {
+ return peekPaused.get();
+ }
+}
--- /dev/null
+/*
+ * 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.computation.queue;
+
+import org.picocontainer.Startable;
+import org.sonar.api.server.ServerSide;
+import org.sonar.db.DbClient;
+import org.sonar.db.DbSession;
+import org.sonar.server.computation.monitoring.CEQueueStatus;
+
+/**
+ * Cleans-up the queue, initializes JMX counters then schedule
+ * the execution of workers. That allows to not prevent workers
+ * from peeking the queue before it's ready.
+ */
+@ServerSide
+public class CeQueueInitializer implements Startable {
+
+ private final DbClient dbClient;
+ private final CEQueueStatus queueStatus;
+ private final CeQueueCleaner cleaner;
+ private final CeProcessingScheduler scheduler;
+
+ public CeQueueInitializer(DbClient dbClient, CEQueueStatus queueStatus, CeQueueCleaner cleaner, CeProcessingScheduler scheduler) {
+ this.dbClient = dbClient;
+ this.queueStatus = queueStatus;
+ this.cleaner = cleaner;
+ this.scheduler = scheduler;
+ }
+
+ @Override
+ public void start() {
+ DbSession dbSession = dbClient.openSession(false);
+ try {
+ initJmxCounters(dbSession);
+ cleaner.clean(dbSession);
+ scheduler.startScheduling();
+
+ } finally {
+ dbClient.closeSession(dbSession);
+ }
+ }
+
+ @Override
+ public void stop() {
+ // nothing to do
+ }
+
+ private void initJmxCounters(DbSession dbSession) {
+ queueStatus.initPendingCount(dbClient.ceQueueDao().countAll(dbSession));
+ }
+}
--- /dev/null
+/*
+ * 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.computation.queue;
+
+import org.sonar.db.ce.CeActivityDto;
+
+public interface CeQueueListener {
+
+ void onRemoved(CeTask task, CeActivityDto.Status status);
+
+}
--- /dev/null
+/*
+ * 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.computation.queue;
+
+import com.google.common.base.Objects;
+import javax.annotation.CheckForNull;
+import javax.annotation.Nullable;
+import javax.annotation.concurrent.Immutable;
+
+import static com.google.common.base.Strings.emptyToNull;
+import static java.util.Objects.requireNonNull;
+
+@Immutable
+public class CeTask {
+
+ private final String type;
+ private final String uuid;
+ private final String componentUuid;
+ private final String componentKey;
+ private final String componentName;
+ private final String submitterLogin;
+
+ private CeTask(Builder builder) {
+ this.uuid = requireNonNull(emptyToNull(builder.uuid));
+ this.type = requireNonNull(emptyToNull(builder.type));
+ this.componentUuid = emptyToNull(builder.componentUuid);
+ this.componentKey = emptyToNull(builder.componentKey);
+ this.componentName = emptyToNull(builder.componentName);
+ this.submitterLogin = emptyToNull(builder.submitterLogin);
+ }
+
+ public String getUuid() {
+ return uuid;
+ }
+
+ public String getType() {
+ return type;
+ }
+
+ @CheckForNull
+ public String getComponentUuid() {
+ return componentUuid;
+ }
+
+ @CheckForNull
+ public String getComponentKey() {
+ return componentKey;
+ }
+
+ @CheckForNull
+ public String getComponentName() {
+ return componentName;
+ }
+
+ @CheckForNull
+ public String getSubmitterLogin() {
+ return submitterLogin;
+ }
+
+ @Override
+ public String toString() {
+ return Objects.toStringHelper(this)
+ .add("componentUuid", componentUuid)
+ .add("uuid", uuid)
+ .add("type", type)
+ .add("submitterLogin", submitterLogin)
+ .toString();
+ }
+
+ @Override
+ public boolean equals(@Nullable Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+ CeTask ceTask = (CeTask) o;
+ return uuid.equals(ceTask.uuid);
+ }
+
+ @Override
+ public int hashCode() {
+ return uuid.hashCode();
+ }
+
+ public static final class Builder {
+ private String uuid;
+ private String type;
+ private String componentUuid;
+ private String componentKey;
+ private String componentName;
+ private String submitterLogin;
+
+ public Builder setUuid(String uuid) {
+ this.uuid = uuid;
+ return this;
+ }
+
+ public Builder setType(String type) {
+ this.type = type;
+ return this;
+ }
+
+ public Builder setComponentUuid(String componentUuid) {
+ this.componentUuid = componentUuid;
+ return this;
+ }
+
+ public Builder setComponentKey(@Nullable String s) {
+ this.componentKey = s;
+ return this;
+ }
+
+ public Builder setComponentName(@Nullable String s) {
+ this.componentName = s;
+ return this;
+ }
+
+ public Builder setSubmitterLogin(@Nullable String s) {
+ this.submitterLogin = s;
+ return this;
+ }
+
+ public CeTask build() {
+ return new CeTask(this);
+ }
+ }
+}
--- /dev/null
+/*
+ * 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.computation.queue;
+
+import java.util.Objects;
+import javax.annotation.CheckForNull;
+import javax.annotation.Nullable;
+import javax.annotation.concurrent.Immutable;
+
+import static com.google.common.base.Strings.emptyToNull;
+
+@Immutable
+public final class CeTaskSubmit {
+
+ private final String uuid;
+ private final String type;
+ private final String componentUuid;
+ private final String submitterLogin;
+
+ private CeTaskSubmit(Builder builder) {
+ this.uuid = Objects.requireNonNull(emptyToNull(builder.uuid));
+ this.type = Objects.requireNonNull(emptyToNull(builder.type));
+ this.componentUuid = emptyToNull(builder.componentUuid);
+ this.submitterLogin = emptyToNull(builder.submitterLogin);
+ }
+
+ public String getType() {
+ return type;
+ }
+
+ public String getUuid() {
+ return uuid;
+ }
+
+ @CheckForNull
+ public String getComponentUuid() {
+ return componentUuid;
+ }
+
+ @CheckForNull
+ public String getSubmitterLogin() {
+ return submitterLogin;
+ }
+
+ public static final class Builder {
+ private final String uuid;
+ private String type;
+ private String componentUuid;
+ private String submitterLogin;
+
+ public Builder(String uuid) {
+ this.uuid = uuid;
+ }
+
+ public String getUuid() {
+ return uuid;
+ }
+
+ public Builder setType(String s) {
+ this.type = s;
+ return this;
+ }
+
+ public Builder setComponentUuid(@Nullable String s) {
+ this.componentUuid = s;
+ return this;
+ }
+
+ public Builder setSubmitterLogin(@Nullable String s) {
+ this.submitterLogin = s;
+ return this;
+ }
+
+ public CeTaskSubmit build() {
+ return new CeTaskSubmit(this);
+ }
+ }
+}
--- /dev/null
+/*
+ * 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.computation.queue;
+
+import com.google.common.base.Optional;
+import org.sonar.api.utils.log.Logger;
+import org.sonar.api.utils.log.Loggers;
+import org.sonar.core.util.logs.Profiler;
+import org.sonar.db.ce.CeActivityDto;
+import org.sonar.server.computation.log.CeLogging;
+import org.sonar.server.computation.queue.report.ReportTaskProcessor;
+
+import static java.lang.String.format;
+
+class CeWorkerRunnable implements Runnable {
+
+ private static final Logger LOG = Loggers.get(CeWorkerRunnable.class);
+
+ private final CeQueue queue;
+ private final ReportTaskProcessor reportTaskProcessor;
+ private final CeLogging ceLogging;
+
+ public CeWorkerRunnable(CeQueue queue, ReportTaskProcessor reportTaskProcessor, CeLogging ceLogging) {
+ this.queue = queue;
+ this.reportTaskProcessor = reportTaskProcessor;
+ this.ceLogging = ceLogging;
+ }
+
+ @Override
+ public void run() {
+ Optional<CeTask> ceTask = tryAndFindTaskToExecute();
+ if (!ceTask.isPresent()) {
+ return;
+ }
+
+ executeTask(ceTask.get());
+ }
+
+ private Optional<CeTask> tryAndFindTaskToExecute() {
+ try {
+ return queue.peek();
+ } catch (Exception e) {
+ LOG.error("Failed to pop the queue of analysis reports", e);
+ }
+ return Optional.absent();
+ }
+
+ private void executeTask(CeTask task) {
+ ceLogging.initForTask(task);
+ Profiler profiler = Profiler.create(LOG).startInfo(format("Analysis of project %s (report %s)", task.getComponentKey(), task.getUuid()));
+ try {
+ // TODO delegate the message to the related task processor, according to task type
+ reportTaskProcessor.process(task);
+ queue.remove(task, CeActivityDto.Status.SUCCESS);
+ } catch (Throwable e) {
+ LOG.error(format("Failed to process task %s", task.getUuid()), e);
+ queue.remove(task, CeActivityDto.Status.FAILED);
+ } finally {
+ profiler.stopInfo(String.format("Total thread execution of project %s (report %s)", task.getComponentUuid(), task.getUuid()));
+ ceLogging.clearForTask();
+ }
+ }
+}
--- /dev/null
+/*
+ * 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.computation.queue;
+
+import javax.annotation.ParametersAreNonnullByDefault;
--- /dev/null
+/*
+ * 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.computation.queue.report;
+
+import org.sonar.db.ce.CeActivityDto;
+import org.sonar.server.computation.ReportFiles;
+import org.sonar.server.computation.queue.CeQueueListener;
+import org.sonar.server.computation.queue.CeTask;
+
+public class CleanReportQueueListener implements CeQueueListener {
+
+ private final ReportFiles reportFiles;
+
+ public CleanReportQueueListener(ReportFiles reportFiles) {
+ this.reportFiles = reportFiles;
+ }
+
+ @Override
+ public void onRemoved(CeTask task, CeActivityDto.Status status) {
+ reportFiles.deleteIfExists(task.getUuid());
+ }
+}
--- /dev/null
+/*
+ * 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.computation.queue.report;
+
+import java.io.InputStream;
+import javax.annotation.Nullable;
+import org.apache.commons.lang.StringUtils;
+import org.sonar.api.resources.Qualifiers;
+import org.sonar.api.server.ServerSide;
+import org.sonar.core.component.ComponentKeys;
+import org.sonar.core.permission.GlobalPermissions;
+import org.sonar.db.ce.CeTaskTypes;
+import org.sonar.db.component.ComponentDto;
+import org.sonar.server.component.ComponentService;
+import org.sonar.server.component.NewComponent;
+import org.sonar.server.computation.ReportFiles;
+import org.sonar.server.computation.queue.CeQueue;
+import org.sonar.server.computation.queue.CeTask;
+import org.sonar.server.computation.queue.CeTaskSubmit;
+import org.sonar.server.permission.PermissionService;
+import org.sonar.server.user.UserSession;
+
+@ServerSide
+public class ReportSubmitter {
+
+ private final CeQueue queue;
+ private final UserSession userSession;
+ private final ReportFiles reportFiles;
+ private final ComponentService componentService;
+ private final PermissionService permissionService;
+
+ public ReportSubmitter(CeQueue queue, UserSession userSession, ReportFiles reportFiles,
+ ComponentService componentService, PermissionService permissionService) {
+ this.queue = queue;
+ this.userSession = userSession;
+ this.reportFiles = reportFiles;
+ this.componentService = componentService;
+ this.permissionService = permissionService;
+ }
+
+ public CeTask submit(String projectKey, @Nullable String projectBranch, @Nullable String projectName, InputStream reportInput) {
+ userSession.checkGlobalPermission(GlobalPermissions.SCAN_EXECUTION);
+
+ String effectiveProjectKey = ComponentKeys.createKey(projectKey, projectBranch);
+ ComponentDto project = componentService.getNullableByKey(effectiveProjectKey);
+ if (project == null) {
+ // the project does not exist -> requires to provision it
+ NewComponent newProject = new NewComponent(projectKey, StringUtils.defaultIfBlank(projectName, projectKey));
+ newProject.setBranch(projectBranch);
+ newProject.setQualifier(Qualifiers.PROJECT);
+ // no need to verify the permission "provisioning" as it's already handled by componentService
+ project = componentService.create(newProject);
+ permissionService.applyDefaultPermissionTemplate(project.getKey());
+ }
+
+ // the report file must be saved before submitting the task
+ CeTaskSubmit.Builder submit = queue.prepareSubmit();
+ reportFiles.save(submit.getUuid(), reportInput);
+
+ submit.setType(CeTaskTypes.REPORT);
+ submit.setComponentUuid(project.uuid());
+ submit.setSubmitterLogin(userSession.getLogin());
+ return queue.submit(submit.build());
+ }
+}
--- /dev/null
+/*
+ * 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.computation.queue.report;
+
+import org.sonar.core.platform.ComponentContainer;
+import org.sonar.server.computation.ComputationStepExecutor;
+import org.sonar.server.computation.container.ComputeEngineContainer;
+import org.sonar.server.computation.container.ContainerFactory;
+import org.sonar.server.computation.queue.CeTask;
+
+public class ReportTaskProcessor {
+
+ private final ContainerFactory containerFactory;
+ private final ComponentContainer serverContainer;
+
+ public ReportTaskProcessor(ContainerFactory containerFactory, ComponentContainer serverContainer) {
+ this.containerFactory = containerFactory;
+ this.serverContainer = serverContainer;
+ }
+
+ public void process(CeTask task) {
+ ComputeEngineContainer ceContainer = containerFactory.create(serverContainer, task);
+ try {
+ ceContainer.getComponentByType(ComputationStepExecutor.class).execute();
+ } finally {
+ ceContainer.cleanup();
+ }
+ }
+}
--- /dev/null
+/*
+ * 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.computation.queue.report;
+
+import javax.annotation.ParametersAreNonnullByDefault;
import org.sonar.api.utils.ZipUtils;
import org.sonar.api.utils.log.Logger;
import org.sonar.api.utils.log.Loggers;
-import org.sonar.server.computation.CeTask;
+import org.sonar.server.computation.queue.CeTask;
import org.sonar.server.computation.ReportFiles;
import org.sonar.server.computation.batch.MutableBatchReportDirectoryHolder;
/**
- * Extracts the content zip file of the {@link org.sonar.server.computation.CeTask} to a temp directory and adds a {@link File}
+ * Extracts the content zip file of the {@link CeTask} to a temp directory and adds a {@link File}
* representing that temp directory to the {@link MutableBatchReportDirectoryHolder}.
*/
public class ExtractReportStep implements ComputationStep {
import org.sonar.api.server.ws.Response;
import org.sonar.api.server.ws.WebService;
import org.sonar.api.web.UserRole;
-import org.sonar.server.computation.CeQueue;
+import org.sonar.server.computation.queue.CeQueue;
import org.sonar.server.user.UserSession;
public class CancelAllWsAction implements CeWsAction {
import org.sonar.api.server.ws.WebService;
import org.sonar.api.web.UserRole;
import org.sonar.core.util.Uuids;
-import org.sonar.server.computation.CeQueue;
+import org.sonar.server.computation.queue.CeQueue;
import org.sonar.server.user.UserSession;
public class CancelWsAction implements CeWsAction {
import org.sonar.api.server.ws.Request;
import org.sonar.api.server.ws.Response;
import org.sonar.api.server.ws.WebService;
-import org.sonar.server.computation.CeTask;
-import org.sonar.server.computation.ReportSubmitter;
+import org.sonar.server.computation.queue.CeTask;
+import org.sonar.server.computation.queue.report.ReportSubmitter;
import org.sonar.server.ws.WsUtils;
import org.sonarqube.ws.WsCe;
import org.sonar.server.component.ws.ComponentsWs;
import org.sonar.server.component.ws.EventsWs;
import org.sonar.server.component.ws.ResourcesWs;
-import org.sonar.server.computation.CeQueueCleaner;
-import org.sonar.server.computation.CeQueueImpl;
-import org.sonar.server.computation.CeQueueInitializer;
-import org.sonar.server.computation.CleanReportQueueListener;
+import org.sonar.server.computation.queue.CeQueueImpl;
+import org.sonar.server.computation.queue.CeQueueCleaner;
+import org.sonar.server.computation.queue.CeQueueInitializer;
+import org.sonar.server.computation.queue.report.CleanReportQueueListener;
import org.sonar.server.computation.ComputeEngineProcessingModule;
import org.sonar.server.computation.ReportFiles;
-import org.sonar.server.computation.ReportSubmitter;
+import org.sonar.server.computation.queue.report.ReportSubmitter;
import org.sonar.server.computation.dbcleaner.IndexPurgeListener;
import org.sonar.server.computation.dbcleaner.ProjectCleaner;
import org.sonar.server.computation.log.CeLogging;
+++ /dev/null
-/*
- * 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.computation;
-
-import java.util.concurrent.TimeUnit;
-import org.junit.Test;
-import org.sonar.server.computation.log.CeLogging;
-
-import static org.mockito.Matchers.any;
-import static org.mockito.Matchers.eq;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.verifyNoMoreInteractions;
-
-public class CeProcessingSchedulerImplTest {
- private CeProcessingSchedulerExecutorService processingExecutorService = mock(CeProcessingSchedulerExecutorService.class);
- private CeQueue ceQueue = mock(CeQueue.class);
- private ReportTaskProcessor reportTaskProcessor = mock(ReportTaskProcessor.class);
- private CeLogging ceLogging = mock(CeLogging.class);
- private CeProcessingSchedulerImpl underTest = new CeProcessingSchedulerImpl(processingExecutorService, ceQueue, reportTaskProcessor, ceLogging);
-
- @Test
- public void startScheduling_schedules_CeWorkerRunnable_at_fixed_rate_run_head_of_queue() {
- underTest.startScheduling();
-
- verify(processingExecutorService).scheduleAtFixedRate(any(CeWorkerRunnable.class), eq(0L), eq(10L), eq(TimeUnit.SECONDS));
- verifyNoMoreInteractions(processingExecutorService);
- }
-
-}
+++ /dev/null
-/*
- * 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.computation;
-
-import java.io.File;
-import java.io.IOException;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.TemporaryFolder;
-import org.mockito.Mockito;
-import org.sonar.api.platform.ServerUpgradeStatus;
-import org.sonar.api.utils.System2;
-import org.sonar.db.DbSession;
-import org.sonar.db.DbTester;
-import org.sonar.db.ce.CeQueueDto;
-import org.sonar.db.ce.CeTaskTypes;
-
-import static java.util.Arrays.asList;
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.mockito.Matchers.any;
-import static org.mockito.Matchers.eq;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-public class CeQueueCleanerTest {
-
- @Rule
- public DbTester dbTester = DbTester.create(System2.INSTANCE);
-
- @Rule
- public TemporaryFolder tempFolder = new TemporaryFolder();
-
- ServerUpgradeStatus serverUpgradeStatus = mock(ServerUpgradeStatus.class);
- ReportFiles reportFiles = mock(ReportFiles.class, Mockito.RETURNS_DEEP_STUBS);
- CeQueueImpl queue = mock(CeQueueImpl.class);
- CeQueueCleaner underTest = new CeQueueCleaner(dbTester.getDbClient(), serverUpgradeStatus, reportFiles, queue);
-
- @Test
- public void reset_in_progress_tasks_to_pending() throws IOException {
- insertInQueue("TASK_1", CeQueueDto.Status.PENDING);
- insertInQueue("TASK_2", CeQueueDto.Status.IN_PROGRESS);
-
- underTest.clean(dbTester.getSession());
-
- assertThat(dbTester.getDbClient().ceQueueDao().countByStatus(dbTester.getSession(), CeQueueDto.Status.PENDING)).isEqualTo(2);
- assertThat(dbTester.getDbClient().ceQueueDao().countByStatus(dbTester.getSession(), CeQueueDto.Status.IN_PROGRESS)).isEqualTo(0);
- }
-
- @Test
- public void clear_queue_if_version_upgrade() {
- when(serverUpgradeStatus.isUpgraded()).thenReturn(true);
-
- underTest.clean(dbTester.getSession());
-
- verify(queue).clear();
- }
-
- @Test
- public void cancel_task_if_report_file_is_missing() throws IOException {
- CeQueueDto task = insertInQueue("TASK_1", CeQueueDto.Status.PENDING, false);
-
- underTest.clean(dbTester.getSession());
-
- verify(queue).cancel(any(DbSession.class), eq(task));
- }
-
- @Test
- public void delete_orphan_report_files() throws Exception {
- // two files on disk but on task in queue
- insertInQueue("TASK_1", CeQueueDto.Status.PENDING, true);
- when(reportFiles.listUuids()).thenReturn(asList("TASK_1", "TASK_2"));
-
- underTest.clean(dbTester.getSession());
-
- verify(reportFiles).deleteIfExists("TASK_2");
- }
-
- private void insertInQueue(String taskUuid, CeQueueDto.Status status) throws IOException {
- insertInQueue(taskUuid, status, true);
- }
-
- private CeQueueDto insertInQueue(String taskUuid, CeQueueDto.Status status, boolean createFile) throws IOException {
- CeQueueDto queueDto = new CeQueueDto();
- queueDto.setTaskType(CeTaskTypes.REPORT);
- queueDto.setComponentUuid("PROJECT_1");
- queueDto.setUuid(taskUuid);
- queueDto.setStatus(status);
- dbTester.getDbClient().ceQueueDao().insert(dbTester.getSession(), queueDto);
- dbTester.getSession().commit();
-
- File file = tempFolder.newFile();
- when(reportFiles.fileForUuid(taskUuid)).thenReturn(file);
- if (!createFile) {
- file.delete();
- }
- return queueDto;
- }
-}
+++ /dev/null
-/*
- * 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.computation;
-
-import com.google.common.base.Optional;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.ExpectedException;
-import org.sonar.api.utils.System2;
-import org.sonar.api.utils.internal.TestSystem2;
-import org.sonar.core.util.UuidFactory;
-import org.sonar.core.util.UuidFactoryImpl;
-import org.sonar.db.DbTester;
-import org.sonar.db.ce.CeActivityDto;
-import org.sonar.db.ce.CeQueueDto;
-import org.sonar.db.ce.CeTaskTypes;
-import org.sonar.server.computation.monitoring.CEQueueStatus;
-import org.sonar.server.computation.monitoring.CEQueueStatusImpl;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.hamcrest.Matchers.startsWith;
-import static org.mockito.Matchers.any;
-import static org.mockito.Matchers.eq;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.verifyZeroInteractions;
-
-public class CeQueueImplTest {
-
- @Rule
- public ExpectedException expectedException = ExpectedException.none();
-
- System2 system2 = new TestSystem2().setNow(1_450_000_000_000L);
-
- @Rule
- public DbTester dbTester = DbTester.create(system2);
-
- UuidFactory uuidFactory = UuidFactoryImpl.INSTANCE;
- CEQueueStatus queueStatus = new CEQueueStatusImpl();
- CeQueueListener listener = mock(CeQueueListener.class);
- CeQueue underTest = new CeQueueImpl(system2, dbTester.getDbClient(), uuidFactory, queueStatus, new CeQueueListener[] {listener});
-
- @Test
- public void test_submit() {
- CeTaskSubmit.Builder submission = underTest.prepareSubmit();
- submission.setComponentUuid("PROJECT_1");
- submission.setType(CeTaskTypes.REPORT);
- submission.setSubmitterLogin("rob");
-
- CeTask task = underTest.submit(submission.build());
- assertThat(task.getUuid()).isEqualTo(submission.getUuid());
- assertThat(task.getComponentUuid()).isEqualTo("PROJECT_1");
- assertThat(task.getSubmitterLogin()).isEqualTo("rob");
-
- Optional<CeQueueDto> queueDto = dbTester.getDbClient().ceQueueDao().selectByUuid(dbTester.getSession(), submission.getUuid());
- assertThat(queueDto.isPresent()).isTrue();
- assertThat(queueDto.get().getTaskType()).isEqualTo(CeTaskTypes.REPORT);
- assertThat(queueDto.get().getComponentUuid()).isEqualTo("PROJECT_1");
- assertThat(queueDto.get().getSubmitterLogin()).isEqualTo("rob");
- assertThat(queueDto.get().getCreatedAt()).isEqualTo(1_450_000_000_000L);
- assertThat(queueStatus.getReceivedCount()).isEqualTo(1L);
- }
-
- @Test
- public void fail_to_submit_if_paused() {
- expectedException.expect(IllegalStateException.class);
- expectedException.expectMessage("Compute Engine does not currently accept new tasks");
- underTest.pauseSubmit();
-
- submit(CeTaskTypes.REPORT, "PROJECT_1");
- }
-
- @Test
- public void test_remove() {
- CeTask task = submit(CeTaskTypes.REPORT, "PROJECT_1");
- Optional<CeTask> peek = underTest.peek();
- underTest.remove(peek.get(), CeActivityDto.Status.SUCCESS);
-
- // queue is empty
- assertThat(dbTester.getDbClient().ceQueueDao().selectByUuid(dbTester.getSession(), task.getUuid()).isPresent()).isFalse();
- assertThat(underTest.peek().isPresent()).isFalse();
-
- // available in history
- Optional<CeActivityDto> history = dbTester.getDbClient().ceActivityDao().selectByUuid(dbTester.getSession(), task.getUuid());
- assertThat(history.isPresent()).isTrue();
- assertThat(history.get().getStatus()).isEqualTo(CeActivityDto.Status.SUCCESS);
- assertThat(history.get().getIsLast()).isTrue();
-
- verify(listener).onRemoved(task, CeActivityDto.Status.SUCCESS);
- }
-
- @Test
- public void fail_to_remove_if_not_in_queue() throws Exception {
- expectedException.expect(IllegalStateException.class);
- CeTask task = submit(CeTaskTypes.REPORT, "PROJECT_1");
- underTest.remove(task, CeActivityDto.Status.SUCCESS);
-
- // fail
- underTest.remove(task, CeActivityDto.Status.SUCCESS);
- }
-
- @Test
- public void test_peek() throws Exception {
- CeTask task = submit(CeTaskTypes.REPORT, "PROJECT_1");
-
- Optional<CeTask> peek = underTest.peek();
- assertThat(peek.isPresent()).isTrue();
- assertThat(peek.get().getUuid()).isEqualTo(task.getUuid());
- assertThat(peek.get().getType()).isEqualTo(CeTaskTypes.REPORT);
- assertThat(peek.get().getComponentUuid()).isEqualTo("PROJECT_1");
-
- // no more pending tasks
- peek = underTest.peek();
- assertThat(peek.isPresent()).isFalse();
-
- verify(listener, never()).onRemoved(eq(task), any(CeActivityDto.Status.class));
- }
-
- @Test
- public void peek_nothing_if_paused() throws Exception {
- submit(CeTaskTypes.REPORT, "PROJECT_1");
- underTest.pausePeek();
-
- Optional<CeTask> peek = underTest.peek();
- assertThat(peek.isPresent()).isFalse();
- }
-
- @Test
- public void cancel_pending() throws Exception {
- CeTask task = submit(CeTaskTypes.REPORT, "PROJECT_1");
-
- // ignore
- boolean canceled = underTest.cancel("UNKNOWN");
- assertThat(canceled).isFalse();
- verifyZeroInteractions(listener);
-
- canceled = underTest.cancel(task.getUuid());
- assertThat(canceled).isTrue();
- Optional<CeActivityDto> activity = dbTester.getDbClient().ceActivityDao().selectByUuid(dbTester.getSession(), task.getUuid());
- assertThat(activity.isPresent()).isTrue();
- assertThat(activity.get().getStatus()).isEqualTo(CeActivityDto.Status.CANCELED);
- verify(listener).onRemoved(task, CeActivityDto.Status.CANCELED);
- }
-
- @Test
- public void fail_to_cancel_if_in_progress() throws Exception {
- expectedException.expect(IllegalStateException.class);
- expectedException.expectMessage(startsWith("Task is in progress and can't be canceled"));
-
- CeTask task = submit(CeTaskTypes.REPORT, "PROJECT_1");
- underTest.peek();
-
- underTest.cancel(task.getUuid());
- }
-
- @Test
- public void cancelAll_pendings_but_not_in_progress() throws Exception {
- CeTask inProgressTask = submit(CeTaskTypes.REPORT, "PROJECT_1");
- CeTask pendingTask1 = submit(CeTaskTypes.REPORT, "PROJECT_2");
- CeTask pendingTask2 = submit(CeTaskTypes.REPORT, "PROJECT_3");
- underTest.peek();
-
- int canceledCount = underTest.cancelAll();
- assertThat(canceledCount).isEqualTo(2);
-
- Optional<CeActivityDto> history = dbTester.getDbClient().ceActivityDao().selectByUuid(dbTester.getSession(), pendingTask1.getUuid());
- assertThat(history.get().getStatus()).isEqualTo(CeActivityDto.Status.CANCELED);
- history = dbTester.getDbClient().ceActivityDao().selectByUuid(dbTester.getSession(), pendingTask2.getUuid());
- assertThat(history.get().getStatus()).isEqualTo(CeActivityDto.Status.CANCELED);
- history = dbTester.getDbClient().ceActivityDao().selectByUuid(dbTester.getSession(), inProgressTask.getUuid());
- assertThat(history.isPresent()).isFalse();
-
- verify(listener).onRemoved(pendingTask1, CeActivityDto.Status.CANCELED);
- verify(listener).onRemoved(pendingTask2, CeActivityDto.Status.CANCELED);
- }
-
- @Test
- public void pause_and_resume_submits() throws Exception {
- assertThat(underTest.isSubmitPaused()).isFalse();
- underTest.pauseSubmit();
- assertThat(underTest.isSubmitPaused()).isTrue();
- underTest.resumeSubmit();
- assertThat(underTest.isSubmitPaused()).isFalse();
- }
-
- @Test
- public void pause_and_resume_peeks() throws Exception {
- assertThat(underTest.isPeekPaused()).isFalse();
- underTest.pausePeek();
- assertThat(underTest.isPeekPaused()).isTrue();
- underTest.resumePeek();
- assertThat(underTest.isPeekPaused()).isFalse();
- }
-
- private CeTask submit(String reportType, String componentUuid) {
- CeTaskSubmit.Builder submission = underTest.prepareSubmit();
- submission.setType(reportType);
- submission.setComponentUuid(componentUuid);
- return underTest.submit(submission.build());
- }
-}
+++ /dev/null
-/*
- * 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.computation;
-
-import java.io.File;
-import java.io.IOException;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.TemporaryFolder;
-import org.mockito.InOrder;
-import org.mockito.Mockito;
-import org.sonar.api.utils.System2;
-import org.sonar.db.DbSession;
-import org.sonar.db.DbTester;
-import org.sonar.db.ce.CeQueueDto;
-import org.sonar.db.ce.CeTaskTypes;
-import org.sonar.server.computation.monitoring.CEQueueStatus;
-import org.sonar.server.computation.monitoring.CEQueueStatusImpl;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.mockito.Matchers.any;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
-
-public class CeQueueInitializerTest {
-
- @Rule
- public DbTester dbTester = DbTester.create(System2.INSTANCE);
-
- @Rule
- public TemporaryFolder tempFolder = new TemporaryFolder();
-
- ReportFiles reportFiles = mock(ReportFiles.class, Mockito.RETURNS_DEEP_STUBS);
- CEQueueStatus queueStatus = new CEQueueStatusImpl();
- CeQueueCleaner cleaner = mock(CeQueueCleaner.class);
- CeProcessingScheduler scheduler = mock(CeProcessingScheduler.class);
- CeQueueInitializer underTest = new CeQueueInitializer(dbTester.getDbClient(), queueStatus, cleaner, scheduler);
-
- @Test
- public void init_jmx_counters() throws IOException {
- insertInQueue("TASK_1", CeQueueDto.Status.PENDING);
- insertInQueue("TASK_2", CeQueueDto.Status.PENDING);
- // this in-progress task is going to be moved to PENDING
- insertInQueue("TASK_3", CeQueueDto.Status.IN_PROGRESS);
-
- underTest.start();
-
- assertThat(queueStatus.getPendingCount()).isEqualTo(3);
- }
-
- @Test
- public void init_jmx_counters_when_queue_is_empty() {
- underTest.start();
-
- assertThat(queueStatus.getPendingCount()).isEqualTo(0);
- }
-
- @Test
- public void clean_queue_then_start_scheduler_of_workers() throws IOException {
- InOrder inOrder = Mockito.inOrder(cleaner, scheduler);
-
- underTest.start();
-
- inOrder.verify(cleaner).clean(any(DbSession.class));
- inOrder.verify(scheduler).startScheduling();
- }
-
- private void insertInQueue(String taskUuid, CeQueueDto.Status status) throws IOException {
- insertInQueue(taskUuid, status, true);
- }
-
- private CeQueueDto insertInQueue(String taskUuid, CeQueueDto.Status status, boolean createFile) throws IOException {
- CeQueueDto queueDto = new CeQueueDto();
- queueDto.setTaskType(CeTaskTypes.REPORT);
- queueDto.setComponentUuid("PROJECT_1");
- queueDto.setUuid(taskUuid);
- queueDto.setStatus(status);
- dbTester.getDbClient().ceQueueDao().insert(dbTester.getSession(), queueDto);
- dbTester.getSession().commit();
-
- File file = tempFolder.newFile();
- when(reportFiles.fileForUuid(taskUuid)).thenReturn(file);
- if (!createFile) {
- file.delete();
- }
- return queueDto;
- }
-}
+++ /dev/null
-/*
- * 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.computation;
-
-import org.junit.Test;
-
-import static org.assertj.core.api.Assertions.assertThat;
-
-public class CeTaskTest {
-
- @Test
- public void build() {
- CeTask.Builder builder = new CeTask.Builder();
- builder.setType("TYPE_1");
- builder.setUuid("UUID_1");
- builder.setSubmitterLogin("LOGIN_1");
- builder.setComponentKey("COMPONENT_KEY_1");
- builder.setComponentUuid("COMPONENT_UUID_1");
- builder.setComponentName("The component");
- CeTask task = builder.build();
-
- assertThat(task.getType()).isEqualTo("TYPE_1");
- assertThat(task.getUuid()).isEqualTo("UUID_1");
- assertThat(task.getSubmitterLogin()).isEqualTo("LOGIN_1");
- assertThat(task.getComponentKey()).isEqualTo("COMPONENT_KEY_1");
- assertThat(task.getComponentUuid()).isEqualTo("COMPONENT_UUID_1");
- assertThat(task.getComponentName()).isEqualTo("The component");
- }
-
- @Test
- public void equals_and_hashCode_on_uuid() {
- CeTask.Builder builder1 = new CeTask.Builder().setType("TYPE_1").setUuid("UUID_1");
- CeTask task1 = builder1.build();
- CeTask task1bis = builder1.build();
- CeTask task2 = new CeTask.Builder().setType("TYPE_1").setUuid("UUID_2").build();
-
- assertThat(task1.equals(task1)).isTrue();
- assertThat(task1.equals(task1bis)).isTrue();
- assertThat(task1.equals(task2)).isFalse();
- assertThat(task1.hashCode()).isEqualTo(task1.hashCode());
- assertThat(task1.hashCode()).isEqualTo(task1bis.hashCode());
- }
-}
+++ /dev/null
-/*
- * 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.computation;
-
-import com.google.common.base.Optional;
-import org.junit.Test;
-import org.mockito.InOrder;
-import org.mockito.Mockito;
-import org.sonar.db.ce.CeActivityDto;
-import org.sonar.db.ce.CeTaskTypes;
-import org.sonar.server.computation.log.CeLogging;
-
-import static org.mockito.Mockito.doThrow;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.verifyZeroInteractions;
-import static org.mockito.Mockito.when;
-
-public class CeWorkerRunnableTest {
-
- CeQueue queue = mock(CeQueueImpl.class);
- ReportTaskProcessor taskProcessor = mock(ReportTaskProcessor.class);
- CeLogging ceLogging = mock(CeLogging.class);
- CeWorkerRunnable underTest = new CeWorkerRunnable(queue, taskProcessor, ceLogging);
-
- @Test
- public void no_pending_tasks_in_queue() throws Exception {
- when(queue.peek()).thenReturn(Optional.<CeTask>absent());
-
- underTest.run();
-
- verifyZeroInteractions(taskProcessor, ceLogging);
- }
-
- @Test
- public void peek_and_process_task() throws Exception {
- CeTask task = new CeTask.Builder().setUuid("TASK_1").setType(CeTaskTypes.REPORT).setComponentUuid("PROJECT_1").setSubmitterLogin(null).build();
- when(queue.peek()).thenReturn(Optional.of(task));
-
- underTest.run();
-
- InOrder inOrder = Mockito.inOrder(ceLogging, taskProcessor, queue);
- inOrder.verify(ceLogging).initForTask(task);
- inOrder.verify(taskProcessor).process(task);
- inOrder.verify(queue).remove(task, CeActivityDto.Status.SUCCESS);
- inOrder.verify(ceLogging).clearForTask();
- }
-
- @Test
- public void fail_to_process_task() throws Exception {
- CeTask task = new CeTask.Builder().setUuid("TASK_1").setType(CeTaskTypes.REPORT).setComponentUuid("PROJECT_1").setSubmitterLogin(null).build();
- when(queue.peek()).thenReturn(Optional.of(task));
- doThrow(new IllegalStateException()).when(taskProcessor).process(task);
-
- underTest.run();
-
- InOrder inOrder = Mockito.inOrder(ceLogging, taskProcessor, queue);
- inOrder.verify(ceLogging).initForTask(task);
- inOrder.verify(taskProcessor).process(task);
- inOrder.verify(queue).remove(task, CeActivityDto.Status.FAILED);
- inOrder.verify(ceLogging).clearForTask();
- }
-}
+++ /dev/null
-/*
- * 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.computation;
-
-import org.junit.Test;
-import org.sonar.db.ce.CeActivityDto;
-import org.sonar.db.ce.CeTaskTypes;
-
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.verify;
-
-public class CleanReportQueueListenerTest {
-
- ReportFiles reportFiles = mock(ReportFiles.class);
- CleanReportQueueListener underTest = new CleanReportQueueListener(reportFiles);
-
- @Test
- public void remove_report_file_if_success() {
- CeTask task = new CeTask.Builder().setUuid("TASK_1").setType(CeTaskTypes.REPORT).setComponentUuid("PROJECT_1").setSubmitterLogin(null).build();
-
- underTest.onRemoved(task, CeActivityDto.Status.SUCCESS);
- verify(reportFiles).deleteIfExists("TASK_1");
- }
-
- @Test
- public void remove_report_file_if_failure() {
- CeTask task = new CeTask.Builder().setUuid("TASK_1").setType(CeTaskTypes.REPORT).setComponentUuid("PROJECT_1").setSubmitterLogin(null).build();
-
- underTest.onRemoved(task, CeActivityDto.Status.FAILED);
- verify(reportFiles).deleteIfExists("TASK_1");
- }
-}
+++ /dev/null
-/*
- * 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.computation;
-
-import org.apache.commons.io.IOUtils;
-import org.hamcrest.Description;
-import org.hamcrest.TypeSafeMatcher;
-import org.junit.Rule;
-import org.junit.Test;
-import org.sonar.core.permission.GlobalPermissions;
-import org.sonar.db.ce.CeTaskTypes;
-import org.sonar.db.component.ComponentDto;
-import org.sonar.server.component.ComponentService;
-import org.sonar.server.component.NewComponent;
-import org.sonar.server.permission.PermissionService;
-import org.sonar.server.tester.UserSessionRule;
-
-import static org.mockito.Matchers.any;
-import static org.mockito.Matchers.argThat;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.verifyZeroInteractions;
-import static org.mockito.Mockito.when;
-
-public class ReportSubmitterTest {
-
- @Rule
- public UserSessionRule userSession = UserSessionRule.standalone();
-
- CeQueue queue = mock(CeQueueImpl.class);
- ReportFiles reportFiles = mock(ReportFiles.class);
- ComponentService componentService = mock(ComponentService.class);
- PermissionService permissionService = mock(PermissionService.class);
- ReportSubmitter underTest = new ReportSubmitter(queue, userSession, reportFiles, componentService, permissionService);
-
- @Test
- public void submit_a_report_on_existing_project() {
- when(queue.prepareSubmit()).thenReturn(new CeTaskSubmit.Builder("TASK_1"));
- userSession.setGlobalPermissions(GlobalPermissions.SCAN_EXECUTION);
- when(componentService.getNullableByKey("MY_PROJECT")).thenReturn(new ComponentDto().setUuid("P1"));
-
- underTest.submit("MY_PROJECT", null, "My Project", IOUtils.toInputStream("{binary}"));
-
- verifyZeroInteractions(permissionService);
- verify(queue).submit(argThat(new TypeSafeMatcher<CeTaskSubmit>() {
- @Override
- protected boolean matchesSafely(CeTaskSubmit submit) {
- return submit.getType().equals(CeTaskTypes.REPORT) && submit.getComponentUuid().equals("P1") &&
- submit.getUuid().equals("TASK_1");
- }
-
- @Override
- public void describeTo(Description description) {
-
- }
- }));
- }
-
- @Test
- public void provision_project_if_does_not_exist() throws Exception {
- when(queue.prepareSubmit()).thenReturn(new CeTaskSubmit.Builder("TASK_1"));
- userSession.setGlobalPermissions(GlobalPermissions.SCAN_EXECUTION, GlobalPermissions.PROVISIONING);
- when(componentService.getNullableByKey("MY_PROJECT")).thenReturn(null);
- when(componentService.create(any(NewComponent.class))).thenReturn(new ComponentDto().setUuid("P1").setKey("MY_PROJECT"));
-
- underTest.submit("MY_PROJECT", null, "My Project", IOUtils.toInputStream("{binary}"));
-
- verify(permissionService).applyDefaultPermissionTemplate("MY_PROJECT");
- verify(queue).submit(argThat(new TypeSafeMatcher<CeTaskSubmit>() {
- @Override
- protected boolean matchesSafely(CeTaskSubmit submit) {
- return submit.getType().equals(CeTaskTypes.REPORT) && submit.getComponentUuid().equals("P1") &&
- submit.getUuid().equals("TASK_1");
- }
-
- @Override
- public void describeTo(Description description) {
-
- }
- }));
-
- }
-}
import javax.annotation.Nullable;
import org.junit.Test;
import org.sonar.core.platform.ComponentContainer;
-import org.sonar.server.computation.CeTask;
+import org.sonar.server.computation.queue.CeTask;
import org.sonar.server.computation.step.ComputationStep;
import static com.google.common.base.Predicates.notNull;
import org.slf4j.MDC;
import org.sonar.api.config.Settings;
import org.sonar.process.ProcessProperties;
-import org.sonar.server.computation.CeTask;
+import org.sonar.server.computation.queue.CeTask;
import static java.lang.String.format;
import static org.assertj.core.api.Assertions.assertThat;
package org.sonar.server.computation.monitoring;
import org.junit.Test;
-import org.sonar.server.computation.CeQueueImpl;
+import org.sonar.server.computation.queue.CeQueueImpl;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.entry;
--- /dev/null
+/*
+ * 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.computation.queue;
+
+import java.util.concurrent.TimeUnit;
+import org.junit.Test;
+import org.sonar.server.computation.queue.report.ReportTaskProcessor;
+import org.sonar.server.computation.log.CeLogging;
+
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyNoMoreInteractions;
+
+public class CeProcessingSchedulerImplTest {
+ private CeProcessingSchedulerExecutorService processingExecutorService = mock(CeProcessingSchedulerExecutorService.class);
+ private CeQueue ceQueue = mock(CeQueue.class);
+ private ReportTaskProcessor reportTaskProcessor = mock(ReportTaskProcessor.class);
+ private CeLogging ceLogging = mock(CeLogging.class);
+ private CeProcessingSchedulerImpl underTest = new CeProcessingSchedulerImpl(processingExecutorService, ceQueue, reportTaskProcessor, ceLogging);
+
+ @Test
+ public void startScheduling_schedules_CeWorkerRunnable_at_fixed_rate_run_head_of_queue() {
+ underTest.startScheduling();
+
+ verify(processingExecutorService).scheduleAtFixedRate(any(CeWorkerRunnable.class), eq(0L), eq(10L), eq(TimeUnit.SECONDS));
+ verifyNoMoreInteractions(processingExecutorService);
+ }
+
+}
--- /dev/null
+/*
+ * 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.computation.queue;
+
+import java.io.File;
+import java.io.IOException;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.TemporaryFolder;
+import org.mockito.Mockito;
+import org.sonar.api.platform.ServerUpgradeStatus;
+import org.sonar.api.utils.System2;
+import org.sonar.db.DbSession;
+import org.sonar.db.DbTester;
+import org.sonar.db.ce.CeQueueDto;
+import org.sonar.db.ce.CeTaskTypes;
+import org.sonar.server.computation.ReportFiles;
+import org.sonar.server.computation.queue.CeQueueCleaner;
+import org.sonar.server.computation.queue.CeQueueImpl;
+
+import static java.util.Arrays.asList;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+public class CeQueueCleanerTest {
+
+ @Rule
+ public DbTester dbTester = DbTester.create(System2.INSTANCE);
+
+ @Rule
+ public TemporaryFolder tempFolder = new TemporaryFolder();
+
+ ServerUpgradeStatus serverUpgradeStatus = mock(ServerUpgradeStatus.class);
+ ReportFiles reportFiles = mock(ReportFiles.class, Mockito.RETURNS_DEEP_STUBS);
+ CeQueueImpl queue = mock(CeQueueImpl.class);
+ CeQueueCleaner underTest = new CeQueueCleaner(dbTester.getDbClient(), serverUpgradeStatus, reportFiles, queue);
+
+ @Test
+ public void reset_in_progress_tasks_to_pending() throws IOException {
+ insertInQueue("TASK_1", CeQueueDto.Status.PENDING);
+ insertInQueue("TASK_2", CeQueueDto.Status.IN_PROGRESS);
+
+ underTest.clean(dbTester.getSession());
+
+ assertThat(dbTester.getDbClient().ceQueueDao().countByStatus(dbTester.getSession(), CeQueueDto.Status.PENDING)).isEqualTo(2);
+ assertThat(dbTester.getDbClient().ceQueueDao().countByStatus(dbTester.getSession(), CeQueueDto.Status.IN_PROGRESS)).isEqualTo(0);
+ }
+
+ @Test
+ public void clear_queue_if_version_upgrade() {
+ when(serverUpgradeStatus.isUpgraded()).thenReturn(true);
+
+ underTest.clean(dbTester.getSession());
+
+ verify(queue).clear();
+ }
+
+ @Test
+ public void cancel_task_if_report_file_is_missing() throws IOException {
+ CeQueueDto task = insertInQueue("TASK_1", CeQueueDto.Status.PENDING, false);
+
+ underTest.clean(dbTester.getSession());
+
+ verify(queue).cancel(any(DbSession.class), eq(task));
+ }
+
+ @Test
+ public void delete_orphan_report_files() throws Exception {
+ // two files on disk but on task in queue
+ insertInQueue("TASK_1", CeQueueDto.Status.PENDING, true);
+ when(reportFiles.listUuids()).thenReturn(asList("TASK_1", "TASK_2"));
+
+ underTest.clean(dbTester.getSession());
+
+ verify(reportFiles).deleteIfExists("TASK_2");
+ }
+
+ private void insertInQueue(String taskUuid, CeQueueDto.Status status) throws IOException {
+ insertInQueue(taskUuid, status, true);
+ }
+
+ private CeQueueDto insertInQueue(String taskUuid, CeQueueDto.Status status, boolean createFile) throws IOException {
+ CeQueueDto queueDto = new CeQueueDto();
+ queueDto.setTaskType(CeTaskTypes.REPORT);
+ queueDto.setComponentUuid("PROJECT_1");
+ queueDto.setUuid(taskUuid);
+ queueDto.setStatus(status);
+ dbTester.getDbClient().ceQueueDao().insert(dbTester.getSession(), queueDto);
+ dbTester.getSession().commit();
+
+ File file = tempFolder.newFile();
+ when(reportFiles.fileForUuid(taskUuid)).thenReturn(file);
+ if (!createFile) {
+ file.delete();
+ }
+ return queueDto;
+ }
+}
--- /dev/null
+/*
+ * 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.computation.queue;
+
+import com.google.common.base.Optional;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.sonar.api.utils.System2;
+import org.sonar.api.utils.internal.TestSystem2;
+import org.sonar.core.util.UuidFactory;
+import org.sonar.core.util.UuidFactoryImpl;
+import org.sonar.db.DbTester;
+import org.sonar.db.ce.CeActivityDto;
+import org.sonar.db.ce.CeQueueDto;
+import org.sonar.db.ce.CeTaskTypes;
+import org.sonar.server.computation.monitoring.CEQueueStatus;
+import org.sonar.server.computation.monitoring.CEQueueStatusImpl;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.hamcrest.Matchers.startsWith;
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyZeroInteractions;
+
+public class CeQueueImplTest {
+
+ @Rule
+ public ExpectedException expectedException = ExpectedException.none();
+
+ System2 system2 = new TestSystem2().setNow(1_450_000_000_000L);
+
+ @Rule
+ public DbTester dbTester = DbTester.create(system2);
+
+ UuidFactory uuidFactory = UuidFactoryImpl.INSTANCE;
+ CEQueueStatus queueStatus = new CEQueueStatusImpl();
+ CeQueueListener listener = mock(CeQueueListener.class);
+ CeQueue underTest = new CeQueueImpl(system2, dbTester.getDbClient(), uuidFactory, queueStatus, new CeQueueListener[] {listener});
+
+ @Test
+ public void test_submit() {
+ CeTaskSubmit.Builder submission = underTest.prepareSubmit();
+ submission.setComponentUuid("PROJECT_1");
+ submission.setType(CeTaskTypes.REPORT);
+ submission.setSubmitterLogin("rob");
+
+ CeTask task = underTest.submit(submission.build());
+ assertThat(task.getUuid()).isEqualTo(submission.getUuid());
+ assertThat(task.getComponentUuid()).isEqualTo("PROJECT_1");
+ assertThat(task.getSubmitterLogin()).isEqualTo("rob");
+
+ Optional<CeQueueDto> queueDto = dbTester.getDbClient().ceQueueDao().selectByUuid(dbTester.getSession(), submission.getUuid());
+ assertThat(queueDto.isPresent()).isTrue();
+ assertThat(queueDto.get().getTaskType()).isEqualTo(CeTaskTypes.REPORT);
+ assertThat(queueDto.get().getComponentUuid()).isEqualTo("PROJECT_1");
+ assertThat(queueDto.get().getSubmitterLogin()).isEqualTo("rob");
+ assertThat(queueDto.get().getCreatedAt()).isEqualTo(1_450_000_000_000L);
+ assertThat(queueStatus.getReceivedCount()).isEqualTo(1L);
+ }
+
+ @Test
+ public void fail_to_submit_if_paused() {
+ expectedException.expect(IllegalStateException.class);
+ expectedException.expectMessage("Compute Engine does not currently accept new tasks");
+ underTest.pauseSubmit();
+
+ submit(CeTaskTypes.REPORT, "PROJECT_1");
+ }
+
+ @Test
+ public void test_remove() {
+ CeTask task = submit(CeTaskTypes.REPORT, "PROJECT_1");
+ Optional<CeTask> peek = underTest.peek();
+ underTest.remove(peek.get(), CeActivityDto.Status.SUCCESS);
+
+ // queue is empty
+ assertThat(dbTester.getDbClient().ceQueueDao().selectByUuid(dbTester.getSession(), task.getUuid()).isPresent()).isFalse();
+ assertThat(underTest.peek().isPresent()).isFalse();
+
+ // available in history
+ Optional<CeActivityDto> history = dbTester.getDbClient().ceActivityDao().selectByUuid(dbTester.getSession(), task.getUuid());
+ assertThat(history.isPresent()).isTrue();
+ assertThat(history.get().getStatus()).isEqualTo(CeActivityDto.Status.SUCCESS);
+ assertThat(history.get().getIsLast()).isTrue();
+
+ verify(listener).onRemoved(task, CeActivityDto.Status.SUCCESS);
+ }
+
+ @Test
+ public void fail_to_remove_if_not_in_queue() throws Exception {
+ expectedException.expect(IllegalStateException.class);
+ CeTask task = submit(CeTaskTypes.REPORT, "PROJECT_1");
+ underTest.remove(task, CeActivityDto.Status.SUCCESS);
+
+ // fail
+ underTest.remove(task, CeActivityDto.Status.SUCCESS);
+ }
+
+ @Test
+ public void test_peek() throws Exception {
+ CeTask task = submit(CeTaskTypes.REPORT, "PROJECT_1");
+
+ Optional<CeTask> peek = underTest.peek();
+ assertThat(peek.isPresent()).isTrue();
+ assertThat(peek.get().getUuid()).isEqualTo(task.getUuid());
+ assertThat(peek.get().getType()).isEqualTo(CeTaskTypes.REPORT);
+ assertThat(peek.get().getComponentUuid()).isEqualTo("PROJECT_1");
+
+ // no more pending tasks
+ peek = underTest.peek();
+ assertThat(peek.isPresent()).isFalse();
+
+ verify(listener, never()).onRemoved(eq(task), any(CeActivityDto.Status.class));
+ }
+
+ @Test
+ public void peek_nothing_if_paused() throws Exception {
+ submit(CeTaskTypes.REPORT, "PROJECT_1");
+ underTest.pausePeek();
+
+ Optional<CeTask> peek = underTest.peek();
+ assertThat(peek.isPresent()).isFalse();
+ }
+
+ @Test
+ public void cancel_pending() throws Exception {
+ CeTask task = submit(CeTaskTypes.REPORT, "PROJECT_1");
+
+ // ignore
+ boolean canceled = underTest.cancel("UNKNOWN");
+ assertThat(canceled).isFalse();
+ verifyZeroInteractions(listener);
+
+ canceled = underTest.cancel(task.getUuid());
+ assertThat(canceled).isTrue();
+ Optional<CeActivityDto> activity = dbTester.getDbClient().ceActivityDao().selectByUuid(dbTester.getSession(), task.getUuid());
+ assertThat(activity.isPresent()).isTrue();
+ assertThat(activity.get().getStatus()).isEqualTo(CeActivityDto.Status.CANCELED);
+ verify(listener).onRemoved(task, CeActivityDto.Status.CANCELED);
+ }
+
+ @Test
+ public void fail_to_cancel_if_in_progress() throws Exception {
+ expectedException.expect(IllegalStateException.class);
+ expectedException.expectMessage(startsWith("Task is in progress and can't be canceled"));
+
+ CeTask task = submit(CeTaskTypes.REPORT, "PROJECT_1");
+ underTest.peek();
+
+ underTest.cancel(task.getUuid());
+ }
+
+ @Test
+ public void cancelAll_pendings_but_not_in_progress() throws Exception {
+ CeTask inProgressTask = submit(CeTaskTypes.REPORT, "PROJECT_1");
+ CeTask pendingTask1 = submit(CeTaskTypes.REPORT, "PROJECT_2");
+ CeTask pendingTask2 = submit(CeTaskTypes.REPORT, "PROJECT_3");
+ underTest.peek();
+
+ int canceledCount = underTest.cancelAll();
+ assertThat(canceledCount).isEqualTo(2);
+
+ Optional<CeActivityDto> history = dbTester.getDbClient().ceActivityDao().selectByUuid(dbTester.getSession(), pendingTask1.getUuid());
+ assertThat(history.get().getStatus()).isEqualTo(CeActivityDto.Status.CANCELED);
+ history = dbTester.getDbClient().ceActivityDao().selectByUuid(dbTester.getSession(), pendingTask2.getUuid());
+ assertThat(history.get().getStatus()).isEqualTo(CeActivityDto.Status.CANCELED);
+ history = dbTester.getDbClient().ceActivityDao().selectByUuid(dbTester.getSession(), inProgressTask.getUuid());
+ assertThat(history.isPresent()).isFalse();
+
+ verify(listener).onRemoved(pendingTask1, CeActivityDto.Status.CANCELED);
+ verify(listener).onRemoved(pendingTask2, CeActivityDto.Status.CANCELED);
+ }
+
+ @Test
+ public void pause_and_resume_submits() throws Exception {
+ assertThat(underTest.isSubmitPaused()).isFalse();
+ underTest.pauseSubmit();
+ assertThat(underTest.isSubmitPaused()).isTrue();
+ underTest.resumeSubmit();
+ assertThat(underTest.isSubmitPaused()).isFalse();
+ }
+
+ @Test
+ public void pause_and_resume_peeks() throws Exception {
+ assertThat(underTest.isPeekPaused()).isFalse();
+ underTest.pausePeek();
+ assertThat(underTest.isPeekPaused()).isTrue();
+ underTest.resumePeek();
+ assertThat(underTest.isPeekPaused()).isFalse();
+ }
+
+ private CeTask submit(String reportType, String componentUuid) {
+ CeTaskSubmit.Builder submission = underTest.prepareSubmit();
+ submission.setType(reportType);
+ submission.setComponentUuid(componentUuid);
+ return underTest.submit(submission.build());
+ }
+}
--- /dev/null
+/*
+ * 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.computation.queue;
+
+import java.io.File;
+import java.io.IOException;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.TemporaryFolder;
+import org.mockito.InOrder;
+import org.mockito.Mockito;
+import org.sonar.api.utils.System2;
+import org.sonar.db.DbSession;
+import org.sonar.db.DbTester;
+import org.sonar.db.ce.CeQueueDto;
+import org.sonar.db.ce.CeTaskTypes;
+import org.sonar.server.computation.ReportFiles;
+import org.sonar.server.computation.monitoring.CEQueueStatus;
+import org.sonar.server.computation.monitoring.CEQueueStatusImpl;
+import org.sonar.server.computation.queue.CeProcessingScheduler;
+import org.sonar.server.computation.queue.CeQueueCleaner;
+import org.sonar.server.computation.queue.CeQueueInitializer;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+public class CeQueueInitializerTest {
+
+ @Rule
+ public DbTester dbTester = DbTester.create(System2.INSTANCE);
+
+ @Rule
+ public TemporaryFolder tempFolder = new TemporaryFolder();
+
+ ReportFiles reportFiles = mock(ReportFiles.class, Mockito.RETURNS_DEEP_STUBS);
+ CEQueueStatus queueStatus = new CEQueueStatusImpl();
+ CeQueueCleaner cleaner = mock(CeQueueCleaner.class);
+ CeProcessingScheduler scheduler = mock(CeProcessingScheduler.class);
+ CeQueueInitializer underTest = new CeQueueInitializer(dbTester.getDbClient(), queueStatus, cleaner, scheduler);
+
+ @Test
+ public void init_jmx_counters() throws IOException {
+ insertInQueue("TASK_1", CeQueueDto.Status.PENDING);
+ insertInQueue("TASK_2", CeQueueDto.Status.PENDING);
+ // this in-progress task is going to be moved to PENDING
+ insertInQueue("TASK_3", CeQueueDto.Status.IN_PROGRESS);
+
+ underTest.start();
+
+ assertThat(queueStatus.getPendingCount()).isEqualTo(3);
+ }
+
+ @Test
+ public void init_jmx_counters_when_queue_is_empty() {
+ underTest.start();
+
+ assertThat(queueStatus.getPendingCount()).isEqualTo(0);
+ }
+
+ @Test
+ public void clean_queue_then_start_scheduler_of_workers() throws IOException {
+ InOrder inOrder = Mockito.inOrder(cleaner, scheduler);
+
+ underTest.start();
+
+ inOrder.verify(cleaner).clean(any(DbSession.class));
+ inOrder.verify(scheduler).startScheduling();
+ }
+
+ private void insertInQueue(String taskUuid, CeQueueDto.Status status) throws IOException {
+ insertInQueue(taskUuid, status, true);
+ }
+
+ private CeQueueDto insertInQueue(String taskUuid, CeQueueDto.Status status, boolean createFile) throws IOException {
+ CeQueueDto queueDto = new CeQueueDto();
+ queueDto.setTaskType(CeTaskTypes.REPORT);
+ queueDto.setComponentUuid("PROJECT_1");
+ queueDto.setUuid(taskUuid);
+ queueDto.setStatus(status);
+ dbTester.getDbClient().ceQueueDao().insert(dbTester.getSession(), queueDto);
+ dbTester.getSession().commit();
+
+ File file = tempFolder.newFile();
+ when(reportFiles.fileForUuid(taskUuid)).thenReturn(file);
+ if (!createFile) {
+ file.delete();
+ }
+ return queueDto;
+ }
+}
--- /dev/null
+/*
+ * 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.computation.queue;
+
+import org.junit.Test;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+public class CeTaskTest {
+
+ @Test
+ public void build() {
+ CeTask.Builder builder = new CeTask.Builder();
+ builder.setType("TYPE_1");
+ builder.setUuid("UUID_1");
+ builder.setSubmitterLogin("LOGIN_1");
+ builder.setComponentKey("COMPONENT_KEY_1");
+ builder.setComponentUuid("COMPONENT_UUID_1");
+ builder.setComponentName("The component");
+ CeTask task = builder.build();
+
+ assertThat(task.getType()).isEqualTo("TYPE_1");
+ assertThat(task.getUuid()).isEqualTo("UUID_1");
+ assertThat(task.getSubmitterLogin()).isEqualTo("LOGIN_1");
+ assertThat(task.getComponentKey()).isEqualTo("COMPONENT_KEY_1");
+ assertThat(task.getComponentUuid()).isEqualTo("COMPONENT_UUID_1");
+ assertThat(task.getComponentName()).isEqualTo("The component");
+ }
+
+ @Test
+ public void equals_and_hashCode_on_uuid() {
+ CeTask.Builder builder1 = new CeTask.Builder().setType("TYPE_1").setUuid("UUID_1");
+ CeTask task1 = builder1.build();
+ CeTask task1bis = builder1.build();
+ CeTask task2 = new CeTask.Builder().setType("TYPE_1").setUuid("UUID_2").build();
+
+ assertThat(task1.equals(task1)).isTrue();
+ assertThat(task1.equals(task1bis)).isTrue();
+ assertThat(task1.equals(task2)).isFalse();
+ assertThat(task1.hashCode()).isEqualTo(task1.hashCode());
+ assertThat(task1.hashCode()).isEqualTo(task1bis.hashCode());
+ }
+}
--- /dev/null
+/*
+ * 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.computation.queue;
+
+import com.google.common.base.Optional;
+import org.junit.Test;
+import org.mockito.InOrder;
+import org.mockito.Mockito;
+import org.sonar.db.ce.CeActivityDto;
+import org.sonar.db.ce.CeTaskTypes;
+import org.sonar.server.computation.queue.report.ReportTaskProcessor;
+import org.sonar.server.computation.log.CeLogging;
+
+import static org.mockito.Mockito.doThrow;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verifyZeroInteractions;
+import static org.mockito.Mockito.when;
+
+public class CeWorkerRunnableTest {
+
+ CeQueue queue = mock(CeQueueImpl.class);
+ ReportTaskProcessor taskProcessor = mock(ReportTaskProcessor.class);
+ CeLogging ceLogging = mock(CeLogging.class);
+ CeWorkerRunnable underTest = new CeWorkerRunnable(queue, taskProcessor, ceLogging);
+
+ @Test
+ public void no_pending_tasks_in_queue() throws Exception {
+ when(queue.peek()).thenReturn(Optional.<CeTask>absent());
+
+ underTest.run();
+
+ verifyZeroInteractions(taskProcessor, ceLogging);
+ }
+
+ @Test
+ public void peek_and_process_task() throws Exception {
+ CeTask task = new CeTask.Builder().setUuid("TASK_1").setType(CeTaskTypes.REPORT).setComponentUuid("PROJECT_1").setSubmitterLogin(null).build();
+ when(queue.peek()).thenReturn(Optional.of(task));
+
+ underTest.run();
+
+ InOrder inOrder = Mockito.inOrder(ceLogging, taskProcessor, queue);
+ inOrder.verify(ceLogging).initForTask(task);
+ inOrder.verify(taskProcessor).process(task);
+ inOrder.verify(queue).remove(task, CeActivityDto.Status.SUCCESS);
+ inOrder.verify(ceLogging).clearForTask();
+ }
+
+ @Test
+ public void fail_to_process_task() throws Exception {
+ CeTask task = new CeTask.Builder().setUuid("TASK_1").setType(CeTaskTypes.REPORT).setComponentUuid("PROJECT_1").setSubmitterLogin(null).build();
+ when(queue.peek()).thenReturn(Optional.of(task));
+ doThrow(new IllegalStateException()).when(taskProcessor).process(task);
+
+ underTest.run();
+
+ InOrder inOrder = Mockito.inOrder(ceLogging, taskProcessor, queue);
+ inOrder.verify(ceLogging).initForTask(task);
+ inOrder.verify(taskProcessor).process(task);
+ inOrder.verify(queue).remove(task, CeActivityDto.Status.FAILED);
+ inOrder.verify(ceLogging).clearForTask();
+ }
+}
--- /dev/null
+/*
+ * 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.computation.queue.report;
+
+import org.junit.Test;
+import org.sonar.db.ce.CeActivityDto;
+import org.sonar.db.ce.CeTaskTypes;
+import org.sonar.server.computation.ReportFiles;
+import org.sonar.server.computation.queue.CeTask;
+
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+
+public class CleanReportQueueListenerTest {
+
+ ReportFiles reportFiles = mock(ReportFiles.class);
+ CleanReportQueueListener underTest = new CleanReportQueueListener(reportFiles);
+
+ @Test
+ public void remove_report_file_if_success() {
+ CeTask task = new CeTask.Builder().setUuid("TASK_1").setType(CeTaskTypes.REPORT).setComponentUuid("PROJECT_1").setSubmitterLogin(null).build();
+
+ underTest.onRemoved(task, CeActivityDto.Status.SUCCESS);
+ verify(reportFiles).deleteIfExists("TASK_1");
+ }
+
+ @Test
+ public void remove_report_file_if_failure() {
+ CeTask task = new CeTask.Builder().setUuid("TASK_1").setType(CeTaskTypes.REPORT).setComponentUuid("PROJECT_1").setSubmitterLogin(null).build();
+
+ underTest.onRemoved(task, CeActivityDto.Status.FAILED);
+ verify(reportFiles).deleteIfExists("TASK_1");
+ }
+}
--- /dev/null
+/*
+ * 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.computation.queue.report;
+
+import org.apache.commons.io.IOUtils;
+import org.hamcrest.Description;
+import org.hamcrest.TypeSafeMatcher;
+import org.junit.Rule;
+import org.junit.Test;
+import org.sonar.core.permission.GlobalPermissions;
+import org.sonar.db.ce.CeTaskTypes;
+import org.sonar.db.component.ComponentDto;
+import org.sonar.server.component.ComponentService;
+import org.sonar.server.component.NewComponent;
+import org.sonar.server.computation.ReportFiles;
+import org.sonar.server.computation.queue.CeQueue;
+import org.sonar.server.computation.queue.CeQueueImpl;
+import org.sonar.server.computation.queue.CeTaskSubmit;
+import org.sonar.server.permission.PermissionService;
+import org.sonar.server.tester.UserSessionRule;
+
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.argThat;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyZeroInteractions;
+import static org.mockito.Mockito.when;
+
+public class ReportSubmitterTest {
+
+ @Rule
+ public UserSessionRule userSession = UserSessionRule.standalone();
+
+ CeQueue queue = mock(CeQueueImpl.class);
+ ReportFiles reportFiles = mock(ReportFiles.class);
+ ComponentService componentService = mock(ComponentService.class);
+ PermissionService permissionService = mock(PermissionService.class);
+ ReportSubmitter underTest = new ReportSubmitter(queue, userSession, reportFiles, componentService, permissionService);
+
+ @Test
+ public void submit_a_report_on_existing_project() {
+ when(queue.prepareSubmit()).thenReturn(new CeTaskSubmit.Builder("TASK_1"));
+ userSession.setGlobalPermissions(GlobalPermissions.SCAN_EXECUTION);
+ when(componentService.getNullableByKey("MY_PROJECT")).thenReturn(new ComponentDto().setUuid("P1"));
+
+ underTest.submit("MY_PROJECT", null, "My Project", IOUtils.toInputStream("{binary}"));
+
+ verifyZeroInteractions(permissionService);
+ verify(queue).submit(argThat(new TypeSafeMatcher<CeTaskSubmit>() {
+ @Override
+ protected boolean matchesSafely(CeTaskSubmit submit) {
+ return submit.getType().equals(CeTaskTypes.REPORT) && submit.getComponentUuid().equals("P1") &&
+ submit.getUuid().equals("TASK_1");
+ }
+
+ @Override
+ public void describeTo(Description description) {
+
+ }
+ }));
+ }
+
+ @Test
+ public void provision_project_if_does_not_exist() throws Exception {
+ when(queue.prepareSubmit()).thenReturn(new CeTaskSubmit.Builder("TASK_1"));
+ userSession.setGlobalPermissions(GlobalPermissions.SCAN_EXECUTION, GlobalPermissions.PROVISIONING);
+ when(componentService.getNullableByKey("MY_PROJECT")).thenReturn(null);
+ when(componentService.create(any(NewComponent.class))).thenReturn(new ComponentDto().setUuid("P1").setKey("MY_PROJECT"));
+
+ underTest.submit("MY_PROJECT", null, "My Project", IOUtils.toInputStream("{binary}"));
+
+ verify(permissionService).applyDefaultPermissionTemplate("MY_PROJECT");
+ verify(queue).submit(argThat(new TypeSafeMatcher<CeTaskSubmit>() {
+ @Override
+ protected boolean matchesSafely(CeTaskSubmit submit) {
+ return submit.getType().equals(CeTaskTypes.REPORT) && submit.getComponentUuid().equals("P1") &&
+ submit.getUuid().equals("TASK_1");
+ }
+
+ @Override
+ public void describeTo(Description description) {
+
+ }
+ }));
+
+ }
+}
import org.junit.Test;
import org.picocontainer.ComponentAdapter;
import org.sonar.core.platform.ComponentContainer;
-import org.sonar.server.computation.CeTask;
+import org.sonar.server.computation.queue.CeTask;
import org.sonar.server.computation.container.ComputeEngineContainerImpl;
import org.sonar.server.computation.container.ReportComputeEngineContainerPopulator;
import org.sonar.server.computation.container.StepsExplorer;
import org.sonar.api.utils.System2;
import org.sonar.api.web.UserRole;
import org.sonar.db.DbTester;
-import org.sonar.server.computation.CeQueue;
+import org.sonar.server.computation.queue.CeQueue;
import org.sonar.server.exceptions.ForbiddenException;
import org.sonar.server.tester.UserSessionRule;
import org.sonar.server.ws.WsActionTester;
import org.sonar.api.utils.System2;
import org.sonar.api.web.UserRole;
import org.sonar.db.DbTester;
-import org.sonar.server.computation.CeQueue;
+import org.sonar.server.computation.queue.CeQueue;
import org.sonar.server.exceptions.ForbiddenException;
import org.sonar.server.tester.UserSessionRule;
import org.sonar.server.ws.WsActionTester;
import org.junit.Test;
import org.mockito.Mockito;
import org.sonar.api.server.ws.WebService;
-import org.sonar.server.computation.ReportSubmitter;
+import org.sonar.server.computation.queue.report.ReportSubmitter;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.mock;
import org.mockito.Matchers;
import org.sonar.core.util.Protobuf;
import org.sonar.db.ce.CeTaskTypes;
-import org.sonar.server.computation.CeTask;
-import org.sonar.server.computation.ReportSubmitter;
+import org.sonar.server.computation.queue.CeTask;
+import org.sonar.server.computation.queue.report.ReportSubmitter;
import org.sonar.server.plugins.MimeTypes;
import org.sonar.server.ws.TestResponse;
import org.sonar.server.ws.WsActionTester;