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;
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() {
+++ /dev/null
-/*
- * Sonar, open source software quality management tool.
- * Copyright (C) 2008-2012 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * Sonar 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.
- *
- * Sonar 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 Sonar; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
- */
-package org.sonar.batch.bootstrap;
-
-import org.slf4j.Logger;
-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.SonarException;
-import org.sonar.batch.ProjectTree;
-
-import static org.sonar.api.utils.DatabaseSemaphore.Lock;
-
-public class CheckSemaphore {
-
- private static final Logger LOG = LoggerFactory.getLogger(CheckSemaphore.class);
-
- private final DatabaseSemaphore databaseSemaphore;
- private final ProjectTree projectTree;
- private final Settings settings;
-
- public CheckSemaphore(DatabaseSemaphore databaseSemaphore, ProjectTree projectTree, Settings settings) {
- this.databaseSemaphore = databaseSemaphore;
- this.projectTree = projectTree;
- this.settings = settings;
- }
-
- public void start() {
- if (!isInDryRunMode()) {
- Lock lock = acquire();
- if (!lock.isAcquired()) {
- LOG.error(getErrorMessage(lock));
- throw new SonarException("The project is already been analysing.");
- }
- }
- }
-
- private String getErrorMessage(Lock lock) {
- long duration = lock.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'.";
- }
-
- public void stop() {
- if (!isInDryRunMode()) {
- release();
- }
- }
-
- private Lock acquire() {
- LOG.debug("Acquire semaphore on project : {}, with key {}", getProject(), getSemaphoreKey());
- if (!isForceAnalyseActivated()) {
- return databaseSemaphore.acquire(getSemaphoreKey());
- } else {
- // In force mode, we acquire the lock regardless there's a existing lock or not
- return databaseSemaphore.acquire(getSemaphoreKey(), 0);
- }
- }
-
- private void release() {
- LOG.debug("Release semaphore on project : {}, with key {}", getProject(), getSemaphoreKey());
- databaseSemaphore.release(getSemaphoreKey());
- }
-
- private String getSemaphoreKey() {
- return "batch-" + getProject().getKey();
- }
-
- private Project getProject() {
- return projectTree.getRootProject();
- }
-
- private boolean isInDryRunMode() {
- return settings.getBoolean(CoreProperties.DRY_RUN);
- }
-
- private boolean isForceAnalyseActivated() {
- return settings.getBoolean(CoreProperties.FORCE_ANALYSIS);
- }
-}
--- /dev/null
+/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2008-2012 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * Sonar 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.
+ *
+ * Sonar 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 Sonar; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
+ */
+package org.sonar.batch.bootstrap;
+
+import org.slf4j.Logger;
+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.Semaphores;
+import org.sonar.api.utils.SonarException;
+import org.sonar.batch.ProjectTree;
+
+public class ProjectLock {
+
+ private static final Logger LOG = LoggerFactory.getLogger(ProjectLock.class);
+
+ private final Semaphores semaphores;
+ private final ProjectTree projectTree;
+ private final Settings settings;
+
+ public ProjectLock(Semaphores semaphores, ProjectTree projectTree, Settings settings) {
+ this.semaphores = semaphores;
+ this.projectTree = projectTree;
+ this.settings = settings;
+ }
+
+ public void start() {
+ if (!isInDryRunMode()) {
+ Semaphores.Semaphore semaphore = acquire();
+ if (!semaphore.isLocked()) {
+ LOG.error(getErrorMessage(semaphore));
+ throw new SonarException("The project is already been analysing.");
+ }
+ }
+ }
+
+ 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'.";
+ }
+
+ public void stop() {
+ if (!isInDryRunMode()) {
+ release();
+ }
+ }
+
+ private Semaphores.Semaphore acquire() {
+ LOG.debug("Acquire semaphore on project : {}, with key {}", getProject(), getSemaphoreKey());
+ if (shouldForce()) {
+ // In force mode, we acquire the lock regardless there's a existing lock or not
+ return semaphores.acquire(getSemaphoreKey(), 0);
+ }
+ return semaphores.acquire(getSemaphoreKey());
+ }
+
+ private void release() {
+ LOG.debug("Release semaphore on project : {}, with key {}", getProject(), getSemaphoreKey());
+ semaphores.release(getSemaphoreKey());
+ }
+
+ private String getSemaphoreKey() {
+ return "batch-" + getProject().getKey();
+ }
+
+ private Project getProject() {
+ return projectTree.getRootProject();
+ }
+
+ private boolean isInDryRunMode() {
+ return settings.getBoolean(CoreProperties.DRY_RUN);
+ }
+
+ private boolean shouldForce() {
+ return settings.getBoolean(CoreProperties.FORCE_ANALYSIS);
+ }
+}
+++ /dev/null
-/*
- * Sonar, open source software quality management tool.
- * Copyright (C) 2008-2012 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * Sonar 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.
- *
- * Sonar 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 Sonar; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
- */
-package org.sonar.batch.bootstrap;
-
-import org.junit.Before;
-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.SonarException;
-import org.sonar.batch.ProjectTree;
-
-import java.util.Date;
-
-import static org.mockito.Matchers.anyInt;
-import static org.mockito.Matchers.anyString;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-import static org.sonar.api.utils.DatabaseSemaphore.Lock;
-
-public class CheckSemaphoreTest {
-
- private CheckSemaphore checkSemaphore;
-
- private DatabaseSemaphore databaseSemaphore;
- 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);
-
- projectTree = mock(ProjectTree.class);
- settings = new Settings();
- setDryRunMode(false);
- setForceMode(false);
-
- project = new Project("key", "branch", "name");
- when(projectTree.getRootProject()).thenReturn(project);
-
- checkSemaphore = new CheckSemaphore(databaseSemaphore, projectTree, settings);
- }
-
- @Test
- public void shouldAcquireSemaphore() {
- when(lock.isAcquired()).thenReturn(true);
- checkSemaphore.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");
- }
-
- @Test
- public void shouldAcquireSemaphoreIfForceAnalyseActivated() {
- setForceMode(true);
- when(lock.isAcquired()).thenReturn(true);
- checkSemaphore.start();
- verify(databaseSemaphore).acquire(anyString(), anyInt());
- }
-
- @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());
- }
-
- @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());
- }
-
- @Test
- public void shouldReleaseSemaphore() {
- checkSemaphore.stop();
- verify(databaseSemaphore).release(anyString());
- }
-
- @Test
- public void shouldNotReleaseSemaphoreInDryRunMode() {
- setDryRunMode(true);
- checkSemaphore.stop();
- verify(databaseSemaphore, never()).release(anyString());
- }
-
- private void setDryRunMode(boolean isInDryRunMode) {
- settings.setProperty(CoreProperties.DRY_RUN, isInDryRunMode);
- }
-
- private void setForceMode(boolean isInForcedMode) {
- settings.setProperty(CoreProperties.FORCE_ANALYSIS, isInForcedMode);
- }
-
-}
--- /dev/null
+/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2008-2012 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * Sonar 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.
+ *
+ * Sonar 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 Sonar; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
+ */
+package org.sonar.batch.bootstrap;
+
+import org.junit.Before;
+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.Semaphores;
+import org.sonar.api.utils.SonarException;
+import org.sonar.batch.ProjectTree;
+
+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;
+
+public class ProjectLockTest {
+
+ private ProjectLock projectLock;
+
+ private Semaphores semaphores;
+ private ProjectTree projectTree;
+ private Settings settings;
+
+ private Project project;
+
+ @Before
+ public void setUp() {
+ semaphores = mock(Semaphores.class);
+
+ projectTree = mock(ProjectTree.class);
+ settings = new Settings();
+ setDryRunMode(false);
+ setForceMode(false);
+ project = new Project("my-project-key");
+ when(projectTree.getRootProject()).thenReturn(project);
+
+ projectLock = new ProjectLock(semaphores, projectTree, settings);
+ }
+
+ @Test
+ public void shouldAcquireSemaphore() {
+ when(semaphores.acquire(anyString())).thenReturn(new Semaphores.Semaphore().setLocked(true));
+ projectLock.start();
+
+ verify(semaphores).acquire("batch-my-project-key");
+ }
+
+ @Test
+ public void shouldAcquireSemaphoreIfForceAnalyseActivated() {
+ setForceMode(true);
+ when(semaphores.acquire("batch-my-project-key", 0)).thenReturn(new Semaphores.Semaphore().setLocked(true));
+
+ projectLock.start();
+ }
+
+ @Test(expected = SonarException.class)
+ public void shouldNotAcquireSemaphoreIfTheProjectIsAlreadyBeenAnalysing() {
+ 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);
+ projectLock.start();
+ verifyZeroInteractions(semaphores);
+ }
+
+ @Test
+ public void shouldReleaseSemaphore() {
+ projectLock.stop();
+ verify(semaphores).release("batch-my-project-key");
+ }
+
+ @Test
+ public void shouldNotReleaseSemaphoreInDryRunMode() {
+ setDryRunMode(true);
+ projectLock.stop();
+ verifyZeroInteractions(semaphores);
+ }
+
+ private void setDryRunMode(boolean isInDryRunMode) {
+ settings.setProperty(CoreProperties.DRY_RUN, isInDryRunMode);
+ }
+
+ private void setForceMode(boolean isInForcedMode) {
+ settings.setProperty(CoreProperties.FORCE_ANALYSIS, isInForcedMode);
+ }
+
+}
+++ /dev/null
-/*
- * Sonar, open source software quality management tool.
- * Copyright (C) 2008-2012 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * Sonar 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.
- *
- * Sonar 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 Sonar; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
- */
-package org.sonar.core.persistence;
-
-import org.sonar.api.utils.DatabaseSemaphore;
-
-/**
- * @since 3.4
- */
-public class DatabaseSemaphoreImpl implements DatabaseSemaphore {
-
- private SemaphoreDao dao;
-
- public DatabaseSemaphoreImpl(SemaphoreDao dao) {
- this.dao = dao;
- }
-
- public Lock acquire(String name, int maxDurationInSeconds) {
- return dao.acquire(name, maxDurationInSeconds);
- }
-
- public Lock acquire(String name) {
- return dao.acquire(name);
- }
-
- public void release(String name) {
- dao.release(name);
- }
-}
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
*/
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);
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);
}
}
- 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();
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 {
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;
}
}
- 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) {
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();
}
--- /dev/null
+/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2008-2012 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * Sonar 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.
+ *
+ * Sonar 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 Sonar; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
+ */
+package org.sonar.core.persistence;
+
+import org.sonar.api.utils.Semaphores;
+
+/**
+ * @since 3.4
+ */
+public class SemaphoresImpl implements Semaphores {
+
+ private SemaphoreDao dao;
+
+ public SemaphoresImpl(SemaphoreDao dao) {
+ this.dao = dao;
+ }
+
+ public Semaphore acquire(String name, int maxDurationInSeconds) {
+ return dao.acquire(name, maxDurationInSeconds);
+ }
+
+ public Semaphore acquire(String name) {
+ return dao.acquire(name);
+ }
+
+ public void release(String name) {
+ dao.release(name);
+ }
+}
+++ /dev/null
-/*
- * Sonar, open source software quality management tool.
- * Copyright (C) 2008-2012 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * Sonar 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.
- *
- * Sonar 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 Sonar; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
- */
-package org.sonar.core.persistence;
-
-import org.junit.Test;
-
-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 {
-
- @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);
-
- DatabaseSemaphoreImpl impl = new DatabaseSemaphoreImpl(dao);
-
- impl.acquire("do-xxx", 50000);
- verify(dao).acquire("do-xxx", 50000);
-
- impl.acquire("do-xxx");
- verify(dao).acquire("do-xxx");
-
- impl.release("do-xxx");
- verify(dao).release("do-xxx");
- }
-}
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;
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 {
@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");
@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");
@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");
@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");
@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");
@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");
@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");
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();
}
}
--- /dev/null
+/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2008-2012 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * Sonar 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.
+ *
+ * Sonar 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 Sonar; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
+ */
+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;
+
+public class SemaphoresImplTest {
+
+ @Test
+ public void should_be_a_bridge_over_dao() {
+ SemaphoreDao dao = mock(SemaphoreDao.class);
+ Semaphores.Semaphore semaphore = new Semaphores.Semaphore();
+ when(dao.acquire(anyString(), anyInt())).thenReturn(semaphore);
+
+ SemaphoresImpl impl = new SemaphoresImpl(dao);
+
+ impl.acquire("do-xxx", 50000);
+ verify(dao).acquire("do-xxx", 50000);
+
+ impl.acquire("do-xxx");
+ verify(dao).acquire("do-xxx");
+
+ impl.release("do-xxx");
+ verify(dao).release("do-xxx");
+ }
+}
+++ /dev/null
-/*
- * Sonar, open source software quality management tool.
- * Copyright (C) 2008-2012 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * Sonar 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.
- *
- * Sonar 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 Sonar; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
- */
-package org.sonar.api.utils;
-
-import org.sonar.api.BatchComponent;
-import org.sonar.api.ServerComponent;
-
-import java.util.Date;
-
-/**
- * A semaphore shared among all the processes that can connect to the central database.
- *
- * @since 3.4
- */
-public interface DatabaseSemaphore 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.
- *
- * @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.
- */
- Lock acquire(String name, int maxDurationInSeconds);
-
- /**
- * Try to acquire the lock on a name.
- * 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);
-
- /**
- * Release the lock on a semaphore by its name.
- *
- * @param name the key of the semaphore
- */
- void release(String name);
-
- class Lock {
-
- private String name;
- private boolean acquired;
- private Date locketAt;
- private Date createdAt;
- private Date updatedAt;
- private Long durationSinceLocked;
-
- public Lock(String name, boolean acquired, Date locketAt, Date createdAt, Date updatedAt) {
- this.name = name;
- this.acquired = acquired;
- this.locketAt = locketAt;
- this.createdAt = createdAt;
- this.updatedAt = updatedAt;
- }
-
- public String getName() {
- return name;
- }
-
- public Date getLocketAt() {
- return locketAt;
- }
-
- public Date getCreatedAt() {
- return createdAt;
- }
-
- public Date getUpdatedAt() {
- return updatedAt;
- }
-
- public boolean isAcquired() {
- return acquired;
- }
-
- public Long getDurationSinceLocked() {
- return durationSinceLocked;
- }
-
- public void setDurationSinceLocked(Long durationSinceLocked) {
- this.durationSinceLocked = durationSinceLocked;
- }
-
- }
-
-}
--- /dev/null
+/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2008-2012 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * Sonar 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.
+ *
+ * Sonar 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 Sonar; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
+ */
+package org.sonar.api.utils;
+
+import org.sonar.api.BatchComponent;
+import org.sonar.api.ServerComponent;
+
+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 Semaphores extends BatchComponent, ServerComponent {
+
+ /**
+ * 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. 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.
+ */
+ Semaphore acquire(String name, int maxDurationInSeconds);
+
+ /**
+ * 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.
+ */
+ Semaphore acquire(String 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 Semaphore {
+
+ private String name;
+ private boolean locked;
+ private Date locketAt;
+ private Date createdAt;
+ private Date updatedAt;
+ private Long durationSinceLocked;
+
+ public String getName() {
+ return name;
+ }
+
+ public Semaphore setName(String name) {
+ this.name = name;
+ return this;
+ }
+
+ 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 Semaphore setUpdatedAt(Date updatedAt) {
+ this.updatedAt = updatedAt;
+ return this;
+ }
+
+ public Long getDurationSinceLocked() {
+ return durationSinceLocked;
+ }
+
+ public Semaphore setDurationSinceLocked(Long durationSinceLocked) {
+ this.durationSinceLocked = durationSinceLocked;
+ return this;
+ }
+ }
+
+}
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;
rootContainer.addSingleton(RuleI18nManager.class);
rootContainer.addSingleton(GwtI18n.class);
rootContainer.addSingleton(DryRunDatabaseFactory.class);
+ rootContainer.addSingleton(SemaphoresImpl.class);
rootContainer.startComponents();
}