FeedIssueComponentUuids.class,
FeedSnapshotsLongDates.class,
FeedIssuesLongDates.class,
- FeedFileSourcesBinaryData.class
+ FeedFileSourcesBinaryData.class,
+ FeedSemaphoresLongDates.class
);
}
--- /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.db.migrations.v51;
+
+import org.sonar.api.utils.System2;
+import org.sonar.core.persistence.Database;
+import org.sonar.server.db.migrations.BaseDataChange;
+import org.sonar.server.db.migrations.MassUpdate;
+import org.sonar.server.db.migrations.Select;
+import org.sonar.server.db.migrations.SqlStatement;
+
+import java.sql.SQLException;
+import java.util.Date;
+
+public class FeedSemaphoresLongDates extends BaseDataChange {
+
+ private final System2 system2;
+
+ public FeedSemaphoresLongDates(Database db, System2 system2) {
+ super(db);
+ this.system2 = system2;
+ }
+
+ @Override
+ public void execute(Context context) throws SQLException {
+ final long now = system2.now();
+ MassUpdate massUpdate = context.prepareMassUpdate();
+ massUpdate
+ .select("SELECT s.created_at, s.updated_at, s.locked_at, s.id FROM semaphores s WHERE created_at_ms IS NULL");
+ massUpdate
+ .update("UPDATE semaphores SET created_at_ms=?, updated_at_ms=?, locked_at_ms=? WHERE id=?");
+ massUpdate.rowPluralName("semaphores");
+ massUpdate.execute(new MassUpdate.Handler() {
+ @Override
+ public boolean handle(Select.Row row, SqlStatement update) throws SQLException {
+ for (int i = 1; i <= 3; i++) {
+ Date date = row.getDate(i);
+ update.setLong(i, date == null ? null : Math.min(now, date.getTime()));
+ }
+
+ Long id = row.getLong(4);
+ update.setLong(4, id);
+
+ return true;
+ }
+ });
+ }
+
+}
--- /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.db.migrations.v51;
+
+import org.junit.Before;
+import org.junit.ClassRule;
+import org.junit.Test;
+import org.sonar.api.utils.System2;
+import org.sonar.core.persistence.DbTester;
+import org.sonar.server.db.migrations.DatabaseMigration;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+import static org.sonar.api.utils.DateUtils.parseDate;
+
+public class FeedSemaphoresLongDatesTest {
+ @ClassRule
+ public static DbTester db = new DbTester().schema(FeedSemaphoresLongDatesTest.class, "schema.sql");
+
+ @Before
+ public void before() throws Exception {
+ db.prepareDbUnit(getClass(), "before.xml");
+ }
+
+ @Test
+ public void execute() throws Exception {
+ DatabaseMigration migration = newMigration(System2.INSTANCE);
+
+ migration.execute();
+
+ int count = db
+ .countSql("select count(*) from semaphores where " +
+ "created_at_ms is not null " +
+ "and updated_at_ms is not null " +
+ "and locked_at_ms is not null");
+ assertThat(count).isEqualTo(2);
+ }
+
+ @Test
+ public void take_now_if_date_in_the_future() throws Exception {
+ System2 system = mock(System2.class);
+ when(system.now()).thenReturn(1234L);
+
+ DatabaseMigration migration = newMigration(system);
+
+ migration.execute();
+
+ int count = db
+ .countSql("select count(*) from semaphores where " +
+ "created_at_ms = 1234");
+ assertThat(count).isEqualTo(1);
+ }
+
+ @Test
+ public void take_snapshot_date_if_in_the_past() throws Exception {
+ DatabaseMigration migration = newMigration(System2.INSTANCE);
+
+ migration.execute();
+
+ long snapshotTime = parseDate("2014-09-25").getTime();
+ int count = db
+ .countSql("select count(*) from semaphores where " +
+ "created_at_ms=" + snapshotTime);
+ assertThat(count).isEqualTo(1);
+ }
+
+ private FeedSemaphoresLongDates newMigration(System2 system) {
+ return new FeedSemaphoresLongDates(db.database(), system);
+ }
+}
--- /dev/null
+<dataset>
+ <!-- new migration -->
+ <semaphores
+ id="1"
+ created_at="2014-09-25"
+ created_at_ms="[null]"
+ updated_at="2014-09-25"
+ updated_at_ms="[null]"
+ locked_at="2014-09-25"
+ locked_at_ms="[null]"
+ />
+
+ <!-- re-entrant migration - ignore the ones that are already fed with new dates -->
+ <semaphores
+ id="2"
+ created_at="2014-09-25"
+ created_at_ms="1500000000"
+ updated_at="2014-09-25"
+ updated_at_ms="1500000000"
+ locked_at="2014-09-25"
+ locked_at_ms="1500000000"
+ />
+
+ <!-- NULL dates -->
+ <semaphores
+ id="3"
+ created_at="[null]"
+ created_at_ms="[null]"
+ updated_at="[null]"
+ updated_at_ms="[null]"
+ locked_at="[null]"
+ locked_at_ms="[null]"
+ />
+</dataset>
--- /dev/null
+CREATE TABLE "SEMAPHORES" (
+ "ID" BIGINT NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1),
+ "CREATED_AT" TIMESTAMP,
+ "CREATED_AT_MS" BIGINT,
+ "LOCKED_AT" TIMESTAMP,
+ "LOCKED_AT_MS" BIGINT,
+ "UPDATED_AT" TIMESTAMP,
+ "UPDATED_AT_MS" BIGINT,
+);
--- /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.
+#
+
+#
+# SonarQube 5.1
+#
+class AddSemaphoresLongDates < ActiveRecord::Migration
+ def self.up
+ add_column 'semaphores', :created_at_ms, :big_integer, :null => true
+ add_column 'semaphores', :updated_at_ms, :big_integer, :null => true
+ add_column 'semaphores', :locked_at_ms, :big_integer, :null => true
+ end
+end
--- /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.
+#
+
+#
+# SonarQube 5.1
+#
+class FeedSemaphoresLongDates < ActiveRecord::Migration
+ def self.up
+ execute_java_migration('org.sonar.server.db.migrations.v51.FeedSemaphoresLongDates')
+ end
+end
+
--- /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.
+#
+
+#
+# SonarQube 5.1
+#
+class RenameSemaphoresLongDates < ActiveRecord::Migration
+ def self.up
+ remove_column 'semaphores', 'created_at'
+ remove_column 'semaphores', 'updated_at'
+ remove_column 'semaphores', 'locked_at'
+ rename_column 'semaphores', 'created_at_ms', 'created_at'
+ rename_column 'semaphores', 'updated_at_ms', 'updated_at'
+ rename_column 'semaphores', 'locked_at_ms', 'locked_at'
+ end
+end
+
*/
public class DatabaseVersion implements BatchComponent, ServerComponent {
- public static final int LAST_VERSION = 783;
+ public static final int LAST_VERSION = 786;
/**
* List of all the tables.n
*/
package org.sonar.core.persistence;
-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 org.sonar.api.utils.System2;
import javax.annotation.CheckForNull;
-import java.util.Date;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import static org.sonar.api.utils.DateUtils.longToDate;
/**
* @since 3.4
private static final String SEMAPHORE_NAME_MUST_NOT_BE_EMPTY = "Semaphore name must not be empty";
private final MyBatis mybatis;
+ private final System2 system;
- public SemaphoreDao(MyBatis mybatis) {
+ public SemaphoreDao(MyBatis mybatis, System2 system) {
this.mybatis = mybatis;
+ this.system = system;
}
public Semaphores.Semaphore acquire(String name, int maxAgeInSeconds) {
- Preconditions.checkArgument(!Strings.isNullOrEmpty(name), SEMAPHORE_NAME_MUST_NOT_BE_EMPTY);
- Preconditions.checkArgument(maxAgeInSeconds >= 0, "Semaphore max age must be positive: " + maxAgeInSeconds);
+ checkArgument(!Strings.isNullOrEmpty(name), SEMAPHORE_NAME_MUST_NOT_BE_EMPTY);
+ checkArgument(maxAgeInSeconds >= 0, "Semaphore max age must be positive: " + maxAgeInSeconds);
- SqlSession session = mybatis.openSession(false);
- try {
- SemaphoreMapper mapper = session.getMapper(SemaphoreMapper.class);
- Date dbNow = mapper.now();
- SemaphoreDto semaphore = tryToInsert(name, dbNow, session);
+ try (SqlSession session = mybatis.openSession(false)) {
+ SemaphoreDto semaphore = tryToInsert(name, system.now(), session);
boolean isAcquired;
if (semaphore == null) {
semaphore = selectSemaphore(name, session);
- isAcquired = acquireIfOutdated(name, maxAgeInSeconds, session, mapper);
+ isAcquired = acquireIfOutdated(name, maxAgeInSeconds, session);
} else {
isAcquired = true;
}
- return createLock(semaphore, session, isAcquired);
- } finally {
- MyBatis.closeQuietly(session);
+ return createLock(semaphore, isAcquired);
}
}
public Semaphores.Semaphore acquire(String name) {
- Preconditions.checkArgument(!Strings.isNullOrEmpty(name), SEMAPHORE_NAME_MUST_NOT_BE_EMPTY);
+ checkArgument(!Strings.isNullOrEmpty(name), SEMAPHORE_NAME_MUST_NOT_BE_EMPTY);
- SqlSession session = mybatis.openSession(false);
- try {
- SemaphoreMapper mapper = session.getMapper(SemaphoreMapper.class);
- Date now = mapper.now();
- SemaphoreDto semaphore = tryToInsert(name, now, session);
+ try (SqlSession session = mybatis.openSession(false)) {
+ SemaphoreDto semaphore = tryToInsert(name, system.now(), session);
if (semaphore == null) {
semaphore = selectSemaphore(name, session);
- return createLock(semaphore, session, false);
+ return createLock(semaphore, false);
} else {
- return createLock(semaphore, session, true);
+ return createLock(semaphore, true);
}
- } finally {
- MyBatis.closeQuietly(session);
}
}
public void update(Semaphores.Semaphore semaphore) {
- Preconditions.checkArgument(semaphore != null, "Semaphore must not be null");
+ checkArgument(semaphore != null, "Semaphore must not be null");
- SqlSession session = mybatis.openSession(false);
- try {
- SemaphoreMapper mapper = session.getMapper(SemaphoreMapper.class);
- mapper.update(semaphore.getName());
+ try (SqlSession session = mybatis.openSession(false)) {
+ mapper(session).update(semaphore.getName(), system.now());
session.commit();
- } finally {
- MyBatis.closeQuietly(session);
}
}
public void release(String name) {
- Preconditions.checkArgument(!Strings.isNullOrEmpty(name), SEMAPHORE_NAME_MUST_NOT_BE_EMPTY);
- SqlSession session = mybatis.openSession(false);
- try {
- session.getMapper(SemaphoreMapper.class).release(name);
+ checkArgument(!Strings.isNullOrEmpty(name), SEMAPHORE_NAME_MUST_NOT_BE_EMPTY);
+ try (SqlSession session = mybatis.openSession(false)) {
+ mapper(session).release(name);
session.commit();
- } finally {
- MyBatis.closeQuietly(session);
}
}
- private boolean acquireIfOutdated(String name, int maxAgeInSeconds, SqlSession session, SemaphoreMapper mapper) {
- Date dbNow = mapper.now();
- Date updatedBefore = DateUtils.addSeconds(dbNow, -maxAgeInSeconds);
- boolean ok = mapper.acquire(name, updatedBefore) == 1;
+ private boolean acquireIfOutdated(String name, int maxAgeInSeconds, SqlSession session) {
+ long now = system.now();
+ long updatedBefore = now - (long) maxAgeInSeconds * 1000;
+
+ boolean ok = mapper(session).acquire(name, updatedBefore, now) == 1;
session.commit();
return ok;
}
* the lock date)
*/
@CheckForNull
- private SemaphoreDto tryToInsert(String name, Date lockedNow, SqlSession session) {
+ private SemaphoreDto tryToInsert(String name, long lockedNow, SqlSession session) {
try {
- SemaphoreMapper mapper = session.getMapper(SemaphoreMapper.class);
+ long now = system.now();
SemaphoreDto semaphore = new SemaphoreDto()
- .setName(name)
- .setLockedAt(lockedNow);
- mapper.initialize(semaphore);
+ .setName(name)
+ .setCreatedAt(now)
+ .setUpdatedAt(now)
+ .setLockedAt(lockedNow);
+ mapper(session).initialize(semaphore);
session.commit();
return semaphore;
} catch (Exception e) {
- // probably because of the semaphore already exists in db
+ // probably because the semaphore already exists in db
session.rollback();
return null;
}
}
- private Semaphores.Semaphore createLock(SemaphoreDto dto, SqlSession session, boolean acquired) {
+ private Semaphores.Semaphore createLock(SemaphoreDto dto, boolean acquired) {
Semaphores.Semaphore semaphore = new Semaphores.Semaphore()
- .setName(dto.getName())
- .setLocked(acquired)
- .setLockedAt(dto.getLockedAt())
- .setCreatedAt(dto.getCreatedAt())
- .setUpdatedAt(dto.getUpdatedAt());
+ .setName(dto.getName())
+ .setLocked(acquired)
+ .setLockedAt(longToDate(dto.getLockedAt()))
+ .setCreatedAt(longToDate(dto.getCreatedAt()))
+ .setUpdatedAt(longToDate(dto.getUpdatedAt()));
if (!acquired) {
- semaphore.setDurationSinceLocked(getDurationSinceLocked(dto, session));
+ semaphore.setDurationSinceLocked(lockedSince(dto));
}
return semaphore;
}
- private long getDurationSinceLocked(SemaphoreDto semaphore, SqlSession session) {
- long now = now(session).getTime();
- semaphore.getLockedAt();
- long lockedAt = semaphore.getLockedAt().getTime();
- return now - lockedAt;
+ private long lockedSince(SemaphoreDto semaphore) {
+ return system.now() - semaphore.getLockedAt();
}
protected SemaphoreDto selectSemaphore(String name, SqlSession session) {
- SemaphoreMapper mapper = session.getMapper(SemaphoreMapper.class);
- return mapper.selectSemaphore(name);
+ return mapper(session).selectSemaphore(name);
}
- protected Date now(SqlSession session) {
- SemaphoreMapper mapper = session.getMapper(SemaphoreMapper.class);
- return mapper.now();
+ private SemaphoreMapper mapper(SqlSession session) {
+ return session.getMapper(SemaphoreMapper.class);
}
-
}
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang.builder.ReflectionToStringBuilder;
-import java.util.Date;
-
/**
* @since 3.4
*/
private Long id;
private String name;
private String checksum;
- private Date lockedAt;
- private Date createdAt;
- private Date updatedAt;
+ private Long lockedAt;
+ private Long createdAt;
+ private Long updatedAt;
public String getName() {
return name;
return this;
}
- public Date getLockedAt() {
+ public Long getLockedAt() {
return lockedAt;
}
- public SemaphoreDto setLockedAt(Date d) {
+ public SemaphoreDto setLockedAt(Long d) {
this.lockedAt = d;
return this;
}
return this;
}
- public Date getCreatedAt() {
+ public Long getCreatedAt() {
return createdAt;
}
- public SemaphoreDto setCreatedAt(Date createdAt) {
+ public SemaphoreDto setCreatedAt(Long createdAt) {
this.createdAt = createdAt;
return this;
}
- public Date getUpdatedAt() {
+ public Long getUpdatedAt() {
return updatedAt;
}
- public SemaphoreDto setUpdatedAt(Date updatedAt) {
+ public SemaphoreDto setUpdatedAt(Long updatedAt) {
this.updatedAt = updatedAt;
return this;
}
import org.apache.ibatis.annotations.Param;
-import java.util.Date;
-
public interface SemaphoreMapper {
int initialize(SemaphoreDto semaphore);
- int acquire(@Param("name") String name, @Param("updatedBefore") Date updatedBefore);
-
- Date now();
+ int acquire(@Param("name") String name, @Param("updatedBefore") Long updatedBefore, @Param("now") Long now);
void release(String name);
SemaphoreDto selectSemaphore(@Param("name") String name);
- void update(String name);
+ void update(@Param("name") String name, @Param("now") Long now);
}
<insert id="initialize" parameterType="map" useGeneratedKeys="false" >
INSERT INTO semaphores (name, checksum, created_at, updated_at, locked_at)
- VALUES (#{name}, #{checksum}, current_timestamp, current_timestamp, #{lockedAt})
+ VALUES (#{name}, #{checksum}, #{createdAt}, #{updatedAt}, #{lockedAt})
</insert>
- <select id="now" resultType="Date" >
- select current_timestamp
- </select>
-
- <select id="now" databaseId="oracle" resultType="Date" >
- select current_timestamp from dual
- </select>
-
<update id="acquire" parameterType="map">
update semaphores
- set updated_at = current_timestamp, locked_at = current_timestamp
+ set updated_at = #{now}, locked_at = #{now}
where name=#{name}
<if test="updatedBefore != null">
AND updated_at < #{updatedBefore}
from semaphores s where s.name=#{name}
</select>
- <update id="update" parameterType="String" >
+ <update id="update" parameterType="map" >
update semaphores
- set updated_at = current_timestamp
+ set updated_at = #{now}
where name=#{name}
</update>
INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('781');
INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('782');
INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('783');
+INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('784');
+INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('785');
+INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('786');
INSERT INTO USERS(ID, LOGIN, NAME, EMAIL, CRYPTED_PASSWORD, SALT, CREATED_AT, UPDATED_AT, REMEMBER_TOKEN, REMEMBER_TOKEN_EXPIRES_AT) VALUES (1, 'admin', 'Administrator', '', 'a373a0e667abb2604c1fd571eb4ad47fe8cc0878', '48bc4b0d93179b5103fd3885ea9119498e9d161b', '1418215735482', '1418215735482', null, null);
ALTER TABLE USERS ALTER COLUMN ID RESTART WITH 2;
"ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1),
"NAME" VARCHAR(4000),
"CHECKSUM" VARCHAR(200),
- "CREATED_AT" TIMESTAMP,
- "UPDATED_AT" TIMESTAMP,
- "LOCKED_AT" TIMESTAMP
+ "CREATED_AT" BIGINT,
+ "UPDATED_AT" BIGINT,
+ "LOCKED_AT" BIGINT
);
CREATE TABLE "MEASURE_FILTERS" (
*/
package org.sonar.core.persistence;
-import org.apache.commons.lang.time.DateUtils;
import org.apache.ibatis.session.SqlSession;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.sonar.api.utils.Semaphores;
+import org.sonar.api.utils.System2;
-import java.util.Date;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.atomic.AtomicInteger;
public class SemaphoreDaoTest extends AbstractDaoTestCase {
private SemaphoreDao dao;
+ private System2 system;
@Before
public void before() {
- dao = new SemaphoreDao(getMyBatis());
+ system = System2.INSTANCE;
+ dao = new SemaphoreDao(getMyBatis(), system);
}
@Rule
thrown.expect(IllegalArgumentException.class);
thrown.expectMessage("Semaphore name must not be empty");
- SemaphoreDao dao = new SemaphoreDao(getMyBatis());
+ SemaphoreDao dao = new SemaphoreDao(getMyBatis(), system);
dao.acquire(null, 5000);
}
thrown.expect(IllegalArgumentException.class);
thrown.expectMessage("Semaphore max age must be positive: -5000");
- SemaphoreDao dao = new SemaphoreDao(getMyBatis());
+ SemaphoreDao dao = new SemaphoreDao(getMyBatis(), system);
dao.acquire("foo", -5000);
}
thrown.expect(IllegalArgumentException.class);
thrown.expectMessage("Semaphore name must not be empty");
- SemaphoreDao dao = new SemaphoreDao(getMyBatis());
+ SemaphoreDao dao = new SemaphoreDao(getMyBatis(), system);
dao.release(null);
}
assertThat(lock.getDurationSinceLocked()).isNull();
SemaphoreDto semaphore = selectSemaphore("foo");
- assertThat(semaphore.getCreatedAt().getTime()).isEqualTo(semaphore.getUpdatedAt().getTime());
+ assertThat(semaphore.getCreatedAt()).isEqualTo(semaphore.getUpdatedAt());
Thread.sleep(1000);
dao.update(lock);
semaphore = selectSemaphore("foo");
- assertThat(semaphore.getCreatedAt().getTime()).isLessThan(semaphore.getUpdatedAt().getTime());
+ assertThat(semaphore.getCreatedAt()).isLessThan(semaphore.getUpdatedAt());
dao.release("foo");
assertThat(selectSemaphore("foo")).isNull();
}
}
- private boolean isRecent(Date date) {
- Date future = DateUtils.addMinutes(now(), 1);
- Date past = DateUtils.addDays(now(), -1);
- return date.after(past) && date.before(future);
- }
-
- private Date now() {
- SqlSession session = getMyBatis().openSession();
- try {
- return dao.now(session);
- } finally {
- MyBatis.closeQuietly(session);
- }
+ private boolean isRecent(Long date) {
+ int oneMinuteInMs = 60 * 1000;
+ long future = system.now() + oneMinuteInMs;
+ long past = system.now() - oneMinuteInMs;
+ return date > past && date < future;
}
private static class Runner extends Thread {
<dataset>
- <semaphores id="1" name="foo" checksum="acbd18db4cc2f85cedef654fccc4a4d8" created_at="2010-01-25" updated_at="2010-01-25" locked_at="2010-01-25"/>
-</dataset>
\ No newline at end of file
+ <semaphores id="1" name="foo" checksum="acbd18db4cc2f85cedef654fccc4a4d8" created_at="1264374000000" updated_at="1264374000000" locked_at="1264374000000"/>
+</dataset>