From af07212b764549c16cd252a9311bb68c642e8179 Mon Sep 17 00:00:00 2001 From: Simon Brandhof Date: Fri, 14 Dec 2012 18:27:29 +0100 Subject: [PATCH] SONAR-3887 refactor semaphore API --- .../sonar/batch/bootstrap/BatchModule.java | 6 +- .../{CheckSemaphore.java => ProjectLock.java} | 43 +++++------ ...emaphoreTest.java => ProjectLockTest.java} | 73 ++++++------------- .../sonar/core/persistence/SemaphoreDao.java | 34 +++++---- ...SemaphoreImpl.java => SemaphoresImpl.java} | 10 +-- .../core/persistence/SemaphoreDaoTest.java | 32 ++++---- ...eImplTest.java => SemaphoresImplTest.java} | 10 +-- ...DatabaseSemaphore.java => Semaphores.java} | 64 ++++++++++------ .../org/sonar/server/platform/Platform.java | 2 + 9 files changed, 134 insertions(+), 140 deletions(-) rename sonar-batch/src/main/java/org/sonar/batch/bootstrap/{CheckSemaphore.java => ProjectLock.java} (64%) rename sonar-batch/src/test/java/org/sonar/batch/bootstrap/{CheckSemaphoreTest.java => ProjectLockTest.java} (57%) rename sonar-core/src/main/java/org/sonar/core/persistence/{DatabaseSemaphoreImpl.java => SemaphoresImpl.java} (81%) rename sonar-core/src/test/java/org/sonar/core/persistence/{DatabaseSemaphoreImplTest.java => SemaphoresImplTest.java} (84%) rename sonar-plugin-api/src/main/java/org/sonar/api/utils/{DatabaseSemaphore.java => Semaphores.java} (62%) diff --git a/sonar-batch/src/main/java/org/sonar/batch/bootstrap/BatchModule.java b/sonar-batch/src/main/java/org/sonar/batch/bootstrap/BatchModule.java index 94448f6f16f..bedc8578223 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/bootstrap/BatchModule.java +++ b/sonar-batch/src/main/java/org/sonar/batch/bootstrap/BatchModule.java @@ -48,7 +48,7 @@ import org.sonar.core.i18n.RuleI18nManager; import org.sonar.core.metric.CacheMetricFinder; import org.sonar.core.notification.DefaultNotificationManager; import org.sonar.core.persistence.DaoUtils; -import org.sonar.core.persistence.DatabaseSemaphoreImpl; +import org.sonar.core.persistence.SemaphoresImpl; import org.sonar.core.persistence.DatabaseVersion; import org.sonar.core.persistence.MyBatis; import org.sonar.core.resource.DefaultResourcePermissions; @@ -104,8 +104,8 @@ public class BatchModule extends Module { container.addSingleton(DefaultUserFinder.class); container.addSingleton(ResourceTypes.class); container.addSingleton(MetricProvider.class); - container.addSingleton(DatabaseSemaphoreImpl.class); - container.addSingleton(CheckSemaphore.class); + container.addSingleton(SemaphoresImpl.class); + container.addSingleton(ProjectLock.class); } private void registerDatabaseComponents() { diff --git a/sonar-batch/src/main/java/org/sonar/batch/bootstrap/CheckSemaphore.java b/sonar-batch/src/main/java/org/sonar/batch/bootstrap/ProjectLock.java similarity index 64% rename from sonar-batch/src/main/java/org/sonar/batch/bootstrap/CheckSemaphore.java rename to sonar-batch/src/main/java/org/sonar/batch/bootstrap/ProjectLock.java index 9bc4b65e621..33a4620a4fc 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/bootstrap/CheckSemaphore.java +++ b/sonar-batch/src/main/java/org/sonar/batch/bootstrap/ProjectLock.java @@ -24,44 +24,42 @@ import org.slf4j.LoggerFactory; import org.sonar.api.CoreProperties; import org.sonar.api.config.Settings; import org.sonar.api.resources.Project; -import org.sonar.api.utils.DatabaseSemaphore; +import org.sonar.api.utils.Semaphores; import org.sonar.api.utils.SonarException; import org.sonar.batch.ProjectTree; -import static org.sonar.api.utils.DatabaseSemaphore.Lock; +public class ProjectLock { -public class CheckSemaphore { + private static final Logger LOG = LoggerFactory.getLogger(ProjectLock.class); - private static final Logger LOG = LoggerFactory.getLogger(CheckSemaphore.class); - - private final DatabaseSemaphore databaseSemaphore; + private final Semaphores semaphores; private final ProjectTree projectTree; private final Settings settings; - public CheckSemaphore(DatabaseSemaphore databaseSemaphore, ProjectTree projectTree, Settings settings) { - this.databaseSemaphore = databaseSemaphore; + public ProjectLock(Semaphores semaphores, ProjectTree projectTree, Settings settings) { + this.semaphores = semaphores; this.projectTree = projectTree; this.settings = settings; } public void start() { if (!isInDryRunMode()) { - Lock lock = acquire(); - if (!lock.isAcquired()) { - LOG.error(getErrorMessage(lock)); + Semaphores.Semaphore semaphore = acquire(); + if (!semaphore.isLocked()) { + LOG.error(getErrorMessage(semaphore)); throw new SonarException("The project is already been analysing."); } } } - private String getErrorMessage(Lock lock) { - long duration = lock.getDurationSinceLocked(); + private String getErrorMessage(Semaphores.Semaphore semaphore) { + long duration = semaphore.getDurationSinceLocked(); DurationLabel durationLabel = new DurationLabel(); String durationDisplay = durationLabel.label(duration); - return "It looks like an analysis of '"+ getProject().getName() +"' is already running (started "+ durationDisplay +"). " + - "If this is not the case, it probably means that previous analysis was interrupted " + - "and you should then force a re-run by using the option '"+ CoreProperties.FORCE_ANALYSIS +"=true'."; + return "It looks like an analysis of '" + getProject().getName() + "' is already running (started " + durationDisplay + "). " + + "If this is not the case, it probably means that previous analysis was interrupted " + + "and you should then force a re-run by using the option '" + CoreProperties.FORCE_ANALYSIS + "=true'."; } public void stop() { @@ -70,19 +68,18 @@ public class CheckSemaphore { } } - private Lock acquire() { + private Semaphores.Semaphore acquire() { LOG.debug("Acquire semaphore on project : {}, with key {}", getProject(), getSemaphoreKey()); - if (!isForceAnalyseActivated()) { - return databaseSemaphore.acquire(getSemaphoreKey()); - } else { + if (shouldForce()) { // In force mode, we acquire the lock regardless there's a existing lock or not - return databaseSemaphore.acquire(getSemaphoreKey(), 0); + return semaphores.acquire(getSemaphoreKey(), 0); } + return semaphores.acquire(getSemaphoreKey()); } private void release() { LOG.debug("Release semaphore on project : {}, with key {}", getProject(), getSemaphoreKey()); - databaseSemaphore.release(getSemaphoreKey()); + semaphores.release(getSemaphoreKey()); } private String getSemaphoreKey() { @@ -97,7 +94,7 @@ public class CheckSemaphore { return settings.getBoolean(CoreProperties.DRY_RUN); } - private boolean isForceAnalyseActivated() { + private boolean shouldForce() { return settings.getBoolean(CoreProperties.FORCE_ANALYSIS); } } diff --git a/sonar-batch/src/test/java/org/sonar/batch/bootstrap/CheckSemaphoreTest.java b/sonar-batch/src/test/java/org/sonar/batch/bootstrap/ProjectLockTest.java similarity index 57% rename from sonar-batch/src/test/java/org/sonar/batch/bootstrap/CheckSemaphoreTest.java rename to sonar-batch/src/test/java/org/sonar/batch/bootstrap/ProjectLockTest.java index e3d09868d9a..f47061a7c0b 100644 --- a/sonar-batch/src/test/java/org/sonar/batch/bootstrap/CheckSemaphoreTest.java +++ b/sonar-batch/src/test/java/org/sonar/batch/bootstrap/ProjectLockTest.java @@ -24,7 +24,7 @@ import org.junit.Test; import org.sonar.api.CoreProperties; import org.sonar.api.config.Settings; import org.sonar.api.resources.Project; -import org.sonar.api.utils.DatabaseSemaphore; +import org.sonar.api.utils.Semaphores; import org.sonar.api.utils.SonarException; import org.sonar.batch.ProjectTree; @@ -32,105 +32,78 @@ import java.util.Date; import static org.mockito.Matchers.anyInt; import static org.mockito.Matchers.anyString; +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; import static org.mockito.Mockito.when; -import static org.sonar.api.utils.DatabaseSemaphore.Lock; -public class CheckSemaphoreTest { +public class ProjectLockTest { - private CheckSemaphore checkSemaphore; + private ProjectLock projectLock; - private DatabaseSemaphore databaseSemaphore; + private Semaphores semaphores; private ProjectTree projectTree; private Settings settings; private Project project; - private Lock lock; @Before public void setUp() { - lock = mock(Lock.class); - - databaseSemaphore = mock(DatabaseSemaphore.class); - when(databaseSemaphore.acquire(anyString())).thenReturn(lock); - when(databaseSemaphore.acquire(anyString(), anyInt())).thenReturn(lock); + semaphores = mock(Semaphores.class); projectTree = mock(ProjectTree.class); settings = new Settings(); setDryRunMode(false); setForceMode(false); - - project = new Project("key", "branch", "name"); + project = new Project("my-project-key"); when(projectTree.getRootProject()).thenReturn(project); - checkSemaphore = new CheckSemaphore(databaseSemaphore, projectTree, settings); + projectLock = new ProjectLock(semaphores, projectTree, settings); } @Test public void shouldAcquireSemaphore() { - when(lock.isAcquired()).thenReturn(true); - checkSemaphore.start(); + when(semaphores.acquire(anyString())).thenReturn(new Semaphores.Semaphore().setLocked(true)); + projectLock.start(); - verify(databaseSemaphore).acquire(anyString()); - } - - @Test - public void shouldUseProjectKeyInTheKeyOfTheSemaphore() { - project = new Project("key"); - when(projectTree.getRootProject()).thenReturn(project); - - when(lock.isAcquired()).thenReturn(true); - checkSemaphore.start(); - - verify(databaseSemaphore).acquire("batch-key"); - } - - @Test - public void shouldUseProjectKeyAndBranchIfExistingInTheKeyOfTheSemaphore() { - when(lock.isAcquired()).thenReturn(true); - checkSemaphore.start(); - - verify(databaseSemaphore).acquire("batch-key:branch"); + verify(semaphores).acquire("batch-my-project-key"); } @Test public void shouldAcquireSemaphoreIfForceAnalyseActivated() { setForceMode(true); - when(lock.isAcquired()).thenReturn(true); - checkSemaphore.start(); - verify(databaseSemaphore).acquire(anyString(), anyInt()); + when(semaphores.acquire("batch-my-project-key", 0)).thenReturn(new Semaphores.Semaphore().setLocked(true)); + + projectLock.start(); } @Test(expected = SonarException.class) public void shouldNotAcquireSemaphoreIfTheProjectIsAlreadyBeenAnalysing() { - when(lock.getLocketAt()).thenReturn(new Date()); - when(lock.isAcquired()).thenReturn(false); - checkSemaphore.start(); - verify(databaseSemaphore, never()).acquire(anyString()); + when(semaphores.acquire(anyString())).thenReturn(new Semaphores.Semaphore().setLocked(false).setDurationSinceLocked(1234L)); + projectLock.start(); } @Test public void shouldNotAcquireSemaphoreInDryRunMode() { setDryRunMode(true); settings = new Settings().setProperty(CoreProperties.DRY_RUN, true); - checkSemaphore.start(); - verify(databaseSemaphore, never()).acquire(anyString()); - verify(databaseSemaphore, never()).acquire(anyString(), anyInt()); + projectLock.start(); + verifyZeroInteractions(semaphores); } @Test public void shouldReleaseSemaphore() { - checkSemaphore.stop(); - verify(databaseSemaphore).release(anyString()); + projectLock.stop(); + verify(semaphores).release("batch-my-project-key"); } @Test public void shouldNotReleaseSemaphoreInDryRunMode() { setDryRunMode(true); - checkSemaphore.stop(); - verify(databaseSemaphore, never()).release(anyString()); + projectLock.stop(); + verifyZeroInteractions(semaphores); } private void setDryRunMode(boolean isInDryRunMode) { diff --git a/sonar-core/src/main/java/org/sonar/core/persistence/SemaphoreDao.java b/sonar-core/src/main/java/org/sonar/core/persistence/SemaphoreDao.java index 471315c2d40..3e36545012b 100644 --- a/sonar-core/src/main/java/org/sonar/core/persistence/SemaphoreDao.java +++ b/sonar-core/src/main/java/org/sonar/core/persistence/SemaphoreDao.java @@ -23,11 +23,10 @@ import com.google.common.base.Preconditions; import com.google.common.base.Strings; import org.apache.commons.lang.time.DateUtils; import org.apache.ibatis.session.SqlSession; +import org.sonar.api.utils.Semaphores; import java.util.Date; -import static org.sonar.api.utils.DatabaseSemaphore.Lock; - /** * @since 3.4 */ @@ -39,7 +38,7 @@ public class SemaphoreDao { this.mybatis = mybatis; } - public Lock acquire(String name, int maxDurationInSeconds) { + public Semaphores.Semaphore acquire(String name, int maxDurationInSeconds) { Preconditions.checkArgument(!Strings.isNullOrEmpty(name), "Semaphore name must not be empty"); Preconditions.checkArgument(maxDurationInSeconds >= 0, "Semaphore max duration must be positive: " + maxDurationInSeconds); @@ -47,7 +46,7 @@ public class SemaphoreDao { try { SemaphoreMapper mapper = session.getMapper(SemaphoreMapper.class); Date lockedAt = org.sonar.api.utils.DateUtils.parseDate("2001-01-01"); - createSemaphore(name, lockedAt, session); + createDto(name, lockedAt, session); boolean isAcquired = doAcquire(name, maxDurationInSeconds, session, mapper); SemaphoreDto semaphore = selectSemaphore(name, session); return createLock(semaphore, session, isAcquired); @@ -56,7 +55,7 @@ public class SemaphoreDao { } } - public Lock acquire(String name) { + public Semaphores.Semaphore acquire(String name) { Preconditions.checkArgument(!Strings.isNullOrEmpty(name), "Semaphore name must not be empty"); SqlSession session = mybatis.openSession(); @@ -67,7 +66,7 @@ public class SemaphoreDao { if (semaphore != null) { return createLock(semaphore, session, false); } else { - semaphore = createSemaphore(name, now, session); + semaphore = createDto(name, now, session); return createLock(semaphore, session, true); } } finally { @@ -93,12 +92,12 @@ public class SemaphoreDao { return ok; } - private SemaphoreDto createSemaphore(String name, Date lockedAt, SqlSession session) { + private SemaphoreDto createDto(String name, Date lockedAt, SqlSession session) { try { SemaphoreMapper mapper = session.getMapper(SemaphoreMapper.class); SemaphoreDto semaphore = new SemaphoreDto() - .setName(name) - .setLockedAt(lockedAt); + .setName(name) + .setLockedAt(lockedAt); mapper.initialize(semaphore); session.commit(); return semaphore; @@ -109,12 +108,17 @@ public class SemaphoreDao { } } - private Lock createLock(SemaphoreDto semaphore, SqlSession session, boolean acquired) { - Lock lock = new Lock(semaphore.getName(), acquired, semaphore.getLockedAt(), semaphore.getCreatedAt(), semaphore.getUpdatedAt()); + private Semaphores.Semaphore createLock(SemaphoreDto dto, SqlSession session, boolean acquired) { + Semaphores.Semaphore semaphore = new Semaphores.Semaphore() + .setName(dto.getName()) + .setLocked(acquired) + .setLocketAt(dto.getLockedAt()) + .setCreatedAt(dto.getCreatedAt()) + .setUpdatedAt(dto.getUpdatedAt()); if (!acquired) { - lock.setDurationSinceLocked(getDurationSinceLocked(semaphore, session)); + semaphore.setDurationSinceLocked(getDurationSinceLocked(dto, session)); } - return lock; + return semaphore; } private long getDurationSinceLocked(SemaphoreDto semaphore, SqlSession session) { @@ -124,12 +128,12 @@ public class SemaphoreDao { return now - locketAt; } - protected SemaphoreDto selectSemaphore(String name, SqlSession session){ + protected SemaphoreDto selectSemaphore(String name, SqlSession session) { SemaphoreMapper mapper = session.getMapper(SemaphoreMapper.class); return mapper.selectSemaphore(name); } - protected Date now(SqlSession session){ + protected Date now(SqlSession session) { SemaphoreMapper mapper = session.getMapper(SemaphoreMapper.class); return mapper.now(); } diff --git a/sonar-core/src/main/java/org/sonar/core/persistence/DatabaseSemaphoreImpl.java b/sonar-core/src/main/java/org/sonar/core/persistence/SemaphoresImpl.java similarity index 81% rename from sonar-core/src/main/java/org/sonar/core/persistence/DatabaseSemaphoreImpl.java rename to sonar-core/src/main/java/org/sonar/core/persistence/SemaphoresImpl.java index 75a5bb7e2ed..b69cff90448 100644 --- a/sonar-core/src/main/java/org/sonar/core/persistence/DatabaseSemaphoreImpl.java +++ b/sonar-core/src/main/java/org/sonar/core/persistence/SemaphoresImpl.java @@ -19,24 +19,24 @@ */ package org.sonar.core.persistence; -import org.sonar.api.utils.DatabaseSemaphore; +import org.sonar.api.utils.Semaphores; /** * @since 3.4 */ -public class DatabaseSemaphoreImpl implements DatabaseSemaphore { +public class SemaphoresImpl implements Semaphores { private SemaphoreDao dao; - public DatabaseSemaphoreImpl(SemaphoreDao dao) { + public SemaphoresImpl(SemaphoreDao dao) { this.dao = dao; } - public Lock acquire(String name, int maxDurationInSeconds) { + public Semaphore acquire(String name, int maxDurationInSeconds) { return dao.acquire(name, maxDurationInSeconds); } - public Lock acquire(String name) { + public Semaphore acquire(String name) { return dao.acquire(name); } diff --git a/sonar-core/src/test/java/org/sonar/core/persistence/SemaphoreDaoTest.java b/sonar-core/src/test/java/org/sonar/core/persistence/SemaphoreDaoTest.java index 948afed4a59..ccfcb6336c3 100644 --- a/sonar-core/src/test/java/org/sonar/core/persistence/SemaphoreDaoTest.java +++ b/sonar-core/src/test/java/org/sonar/core/persistence/SemaphoreDaoTest.java @@ -25,6 +25,7 @@ import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; +import org.sonar.api.utils.Semaphores; import java.util.Date; import java.util.concurrent.CountDownLatch; @@ -32,7 +33,6 @@ import java.util.concurrent.CyclicBarrier; import java.util.concurrent.atomic.AtomicInteger; import static org.fest.assertions.Assertions.assertThat; -import static org.sonar.api.utils.DatabaseSemaphore.Lock; public class SemaphoreDaoTest extends AbstractDaoTestCase { @@ -75,8 +75,8 @@ public class SemaphoreDaoTest extends AbstractDaoTestCase { @Test public void create_and_acquire_semaphore() throws Exception { - Lock lock = dao.acquire("foo", 60); - assertThat(lock.isAcquired()).isTrue(); + Semaphores.Semaphore lock = dao.acquire("foo", 60); + assertThat(lock.isLocked()).isTrue(); assertThat(lock.getDurationSinceLocked()).isNull(); SemaphoreDto semaphore = selectSemaphore("foo"); @@ -92,8 +92,8 @@ public class SemaphoreDaoTest extends AbstractDaoTestCase { @Test public void create_and_acquire_semaphore_when_timeout_is_zeo() throws Exception { - Lock lock = dao.acquire("foo", 0); - assertThat(lock.isAcquired()).isTrue(); + Semaphores.Semaphore lock = dao.acquire("foo", 0); + assertThat(lock.isLocked()).isTrue(); assertThat(lock.getDurationSinceLocked()).isNull(); SemaphoreDto semaphore = selectSemaphore("foo"); @@ -109,8 +109,8 @@ public class SemaphoreDaoTest extends AbstractDaoTestCase { @Test public void create_and_acquire_semaphore_when_no_timeout() throws Exception { - Lock lock = dao.acquire("foo"); - assertThat(lock.isAcquired()).isTrue(); + Semaphores.Semaphore lock = dao.acquire("foo"); + assertThat(lock.isLocked()).isTrue(); assertThat(lock.getDurationSinceLocked()).isNull(); SemaphoreDto semaphore = selectSemaphore("foo"); @@ -127,8 +127,8 @@ public class SemaphoreDaoTest extends AbstractDaoTestCase { @Test public void fail_to_acquire_locked_semaphore() throws Exception { setupData("old_semaphore"); - Lock lock = dao.acquire("foo", Integer.MAX_VALUE); - assertThat(lock.isAcquired()).isFalse(); + Semaphores.Semaphore lock = dao.acquire("foo", Integer.MAX_VALUE); + assertThat(lock.isLocked()).isFalse(); assertThat(lock.getDurationSinceLocked()).isNotNull(); SemaphoreDto semaphore = selectSemaphore("foo"); @@ -142,8 +142,8 @@ public class SemaphoreDaoTest extends AbstractDaoTestCase { @Test public void acquire_long_locked_semaphore() throws Exception { setupData("old_semaphore"); - Lock lock = dao.acquire("foo", 60); - assertThat(lock.isAcquired()).isTrue(); + Semaphores.Semaphore lock = dao.acquire("foo", 60); + assertThat(lock.isLocked()).isTrue(); assertThat(lock.getDurationSinceLocked()).isNull(); SemaphoreDto semaphore = selectSemaphore("foo"); @@ -157,8 +157,8 @@ public class SemaphoreDaoTest extends AbstractDaoTestCase { @Test public void acquire_locked_semaphore_when_timeout_is_zeo() throws Exception { setupData("old_semaphore"); - Lock lock = dao.acquire("foo", 0); - assertThat(lock.isAcquired()).isTrue(); + Semaphores.Semaphore lock = dao.acquire("foo", 0); + assertThat(lock.isLocked()).isTrue(); assertThat(lock.getDurationSinceLocked()).isNull(); SemaphoreDto semaphore = selectSemaphore("foo"); @@ -175,8 +175,8 @@ public class SemaphoreDaoTest extends AbstractDaoTestCase { @Test public void fail_to_acquire_locked_semaphore_when_no_timeout() throws Exception { setupData("old_semaphore"); - Lock lock = dao.acquire("foo"); - assertThat(lock.isAcquired()).isFalse(); + Semaphores.Semaphore lock = dao.acquire("foo"); + assertThat(lock.isLocked()).isFalse(); assertThat(lock.getDurationSinceLocked()).isNotNull(); SemaphoreDto semaphore = selectSemaphore("foo"); @@ -259,7 +259,7 @@ public class SemaphoreDaoTest extends AbstractDaoTestCase { try { barrier.await(); for (int i = 0; i < 100; i++) { - if (dao.acquire("my-lock", 60 * 5).isAcquired()) { + if (dao.acquire("my-lock", 60 * 5).isLocked()) { locks.incrementAndGet(); } } diff --git a/sonar-core/src/test/java/org/sonar/core/persistence/DatabaseSemaphoreImplTest.java b/sonar-core/src/test/java/org/sonar/core/persistence/SemaphoresImplTest.java similarity index 84% rename from sonar-core/src/test/java/org/sonar/core/persistence/DatabaseSemaphoreImplTest.java rename to sonar-core/src/test/java/org/sonar/core/persistence/SemaphoresImplTest.java index 73a7d61396b..a09b49a3048 100644 --- a/sonar-core/src/test/java/org/sonar/core/persistence/DatabaseSemaphoreImplTest.java +++ b/sonar-core/src/test/java/org/sonar/core/persistence/SemaphoresImplTest.java @@ -20,23 +20,23 @@ package org.sonar.core.persistence; import org.junit.Test; +import org.sonar.api.utils.Semaphores; import static org.mockito.Matchers.anyInt; import static org.mockito.Matchers.anyString; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; -import static org.sonar.api.utils.DatabaseSemaphore.Lock; -public class DatabaseSemaphoreImplTest { +public class SemaphoresImplTest { @Test public void should_be_a_bridge_over_dao() { - Lock lock = mock(Lock.class); SemaphoreDao dao = mock(SemaphoreDao.class); - when(dao.acquire(anyString(), anyInt())).thenReturn(lock); + Semaphores.Semaphore semaphore = new Semaphores.Semaphore(); + when(dao.acquire(anyString(), anyInt())).thenReturn(semaphore); - DatabaseSemaphoreImpl impl = new DatabaseSemaphoreImpl(dao); + SemaphoresImpl impl = new SemaphoresImpl(dao); impl.acquire("do-xxx", 50000); verify(dao).acquire("do-xxx", 50000); diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/utils/DatabaseSemaphore.java b/sonar-plugin-api/src/main/java/org/sonar/api/utils/Semaphores.java similarity index 62% rename from sonar-plugin-api/src/main/java/org/sonar/api/utils/DatabaseSemaphore.java rename to sonar-plugin-api/src/main/java/org/sonar/api/utils/Semaphores.java index 93d8ef9075a..1b3a7116fb2 100644 --- a/sonar-plugin-api/src/main/java/org/sonar/api/utils/DatabaseSemaphore.java +++ b/sonar-plugin-api/src/main/java/org/sonar/api/utils/Semaphores.java @@ -26,82 +26,100 @@ import java.util.Date; /** * A semaphore shared among all the processes that can connect to the central database. + * It's ignored when enabling the dry run mode. * * @since 3.4 */ -public interface DatabaseSemaphore extends BatchComponent, ServerComponent { +public interface Semaphores extends BatchComponent, ServerComponent { /** - * Try to acquire a lock on a name, for a given duration. - * The lock will be acquired if there's no existing lock on this name or if a lock exists but the max duration is reached. + * Try to acquire a semaphore for a given duration. + * The semaphore is acquired if it's unlocked or if the max locking duration is reached. * - * @param name the key of the semaphore - * @param maxDurationInSeconds the max duration in seconds the semaphore will be acquired (a value of zero can be used to always acquire a lock) - * @return a lock containing information if the lock could be acquired or not, the duration since locked, etc. + * @param name the key of the semaphore + * @param maxDurationInSeconds the max duration in seconds the semaphore will be acquired. The value zero forces the semaphore to be acquired, whatever its status. + * @return the semaphore, whatever its status (locked or unlocked). Can't be null. */ - Lock acquire(String name, int maxDurationInSeconds); + Semaphore acquire(String name, int maxDurationInSeconds); /** - * Try to acquire the lock on a name. + * Try to acquire a semaphore. * The lock will be acquired only if there's no existing lock. * * @param name the key of the semaphore * @return a lock containing information if the lock could be acquired or not, the duration since locked, etc. */ - Lock acquire(String name); + Semaphore acquire(String name); /** - * Release the lock on a semaphore by its name. + * Release the lock on a semaphore by its name. Does nothing if the lock is already released. * * @param name the key of the semaphore */ void release(String name); - class Lock { + class Semaphore { private String name; - private boolean acquired; + private boolean locked; private Date locketAt; private Date createdAt; private Date updatedAt; private Long durationSinceLocked; - public Lock(String name, boolean acquired, Date locketAt, Date createdAt, Date updatedAt) { + public String getName() { + return name; + } + + public Semaphore setName(String name) { this.name = name; - this.acquired = acquired; - this.locketAt = locketAt; - this.createdAt = createdAt; - this.updatedAt = updatedAt; + return this; } - public String getName() { - return name; + public boolean isLocked() { + return locked; + } + + public Semaphore setLocked(boolean locked) { + this.locked = locked; + return this; } public Date getLocketAt() { return locketAt; } + public Semaphore setLocketAt(Date locketAt) { + this.locketAt = locketAt; + return this; + } + public Date getCreatedAt() { return createdAt; } + public Semaphore setCreatedAt(Date createdAt) { + this.createdAt = createdAt; + return this; + } + public Date getUpdatedAt() { return updatedAt; } - public boolean isAcquired() { - return acquired; + public Semaphore setUpdatedAt(Date updatedAt) { + this.updatedAt = updatedAt; + return this; } public Long getDurationSinceLocked() { return durationSinceLocked; } - public void setDurationSinceLocked(Long durationSinceLocked) { + public Semaphore setDurationSinceLocked(Long durationSinceLocked) { this.durationSinceLocked = durationSinceLocked; + return this; } - } } diff --git a/sonar-server/src/main/java/org/sonar/server/platform/Platform.java b/sonar-server/src/main/java/org/sonar/server/platform/Platform.java index 9809d4816c6..eff0770fcf3 100644 --- a/sonar-server/src/main/java/org/sonar/server/platform/Platform.java +++ b/sonar-server/src/main/java/org/sonar/server/platform/Platform.java @@ -51,6 +51,7 @@ import org.sonar.core.persistence.DatabaseVersion; import org.sonar.core.persistence.DefaultDatabase; import org.sonar.core.persistence.DryRunDatabaseFactory; import org.sonar.core.persistence.MyBatis; +import org.sonar.core.persistence.SemaphoresImpl; import org.sonar.core.qualitymodel.DefaultModelFinder; import org.sonar.core.resource.DefaultResourcePermissions; import org.sonar.core.rule.DefaultRuleFinder; @@ -181,6 +182,7 @@ public final class Platform { rootContainer.addSingleton(RuleI18nManager.class); rootContainer.addSingleton(GwtI18n.class); rootContainer.addSingleton(DryRunDatabaseFactory.class); + rootContainer.addSingleton(SemaphoresImpl.class); rootContainer.startComponents(); } -- 2.39.5