aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSébastien Lesaint <sebastien.lesaint@sonarsource.com>2016-12-06 12:19:29 +0100
committerSébastien Lesaint <sebastien.lesaint@sonarsource.com>2016-12-06 12:19:29 +0100
commitf37be4d76f5615f249a11d8c88aa0482bb84f21a (patch)
tree7aa220e885a72b34f5feb58b7cea72bf03e2ac88
parent79a8e50ccd27c442e35a757bca181d783e99b1ba (diff)
parentaea44b9d8f223e201b5a4a2f0d85206880e76de5 (diff)
downloadsonarqube-f37be4d76f5615f249a11d8c88aa0482bb84f21a.tar.gz
sonarqube-f37be4d76f5615f249a11d8c88aa0482bb84f21a.zip
Merge branch 'branch-6.2'
-rw-r--r--sonar-core/src/main/java/org/sonar/core/util/UuidGeneratorImpl.java18
-rw-r--r--sonar-core/src/test/java/org/sonar/core/util/UuidGeneratorImplTest.java61
-rw-r--r--sonar-db/src/main/java/org/sonar/db/ce/CeActivityDao.java13
-rw-r--r--sonar-db/src/main/java/org/sonar/db/ce/CeActivityMapper.java5
-rw-r--r--sonar-db/src/main/resources/org/sonar/db/ce/CeActivityMapper.xml15
5 files changed, 76 insertions, 36 deletions
diff --git a/sonar-core/src/main/java/org/sonar/core/util/UuidGeneratorImpl.java b/sonar-core/src/main/java/org/sonar/core/util/UuidGeneratorImpl.java
index f76adf7e0cc..2b3b13d7f92 100644
--- a/sonar-core/src/main/java/org/sonar/core/util/UuidGeneratorImpl.java
+++ b/sonar-core/src/main/java/org/sonar/core/util/UuidGeneratorImpl.java
@@ -38,7 +38,6 @@ public final class UuidGeneratorImpl implements UuidGenerator {
}
private static class UuidGeneratorBase {
- private final byte[] buffer = new byte[15];
// We only use bottom 3 bytes for the sequence number. Paranoia: init with random int so that if JVM/OS/machine goes down, clock slips
// backwards, and JVM comes back up, we are less likely to be on the same sequenceNumber at the same time:
private final AtomicInteger sequenceNumber = new AtomicInteger(new SecureRandom().nextInt());
@@ -46,7 +45,7 @@ public final class UuidGeneratorImpl implements UuidGenerator {
// Used to ensure clock moves forward
private long lastTimestamp = 0L;
- void initBase(int sequenceId) {
+ void initBase(byte[] buffer, int sequenceId) {
long timestamp = System.currentTimeMillis();
synchronized (this) {
@@ -70,7 +69,7 @@ public final class UuidGeneratorImpl implements UuidGenerator {
System.arraycopy(secureMungedAddress, 0, buffer, 6, secureMungedAddress.length);
}
- protected byte[] generate(int increment) {
+ protected byte[] generate(byte[] buffer, int increment) {
// Sequence number adds 3 bytes
putLong(buffer, increment, 12, 3);
@@ -93,21 +92,26 @@ public final class UuidGeneratorImpl implements UuidGenerator {
@Override
public byte[] get() {
+ byte[] buffer = new byte[15];
int sequenceId = getSequenceId();
- initBase(sequenceId);
- return super.generate(sequenceId);
+ initBase(buffer, sequenceId);
+ return super.generate(buffer, sequenceId);
}
}
private static class FixedBasedUuidGenerator extends UuidGeneratorBase implements WithFixedBase {
+ private final byte[] base = new byte[15];
+
FixedBasedUuidGenerator() {
int sequenceId = getSequenceId();
- initBase(sequenceId);
+ initBase(base, sequenceId);
}
@Override
public byte[] generate(int increment) {
- return super.generate(increment);
+ byte[] buffer = new byte[15];
+ System.arraycopy(base, 0, buffer, 0, buffer.length);
+ return super.generate(buffer, increment);
}
}
}
diff --git a/sonar-core/src/test/java/org/sonar/core/util/UuidGeneratorImplTest.java b/sonar-core/src/test/java/org/sonar/core/util/UuidGeneratorImplTest.java
index 21200b0aa40..175aec720c6 100644
--- a/sonar-core/src/test/java/org/sonar/core/util/UuidGeneratorImplTest.java
+++ b/sonar-core/src/test/java/org/sonar/core/util/UuidGeneratorImplTest.java
@@ -19,10 +19,13 @@
*/
package org.sonar.core.util;
+import java.util.ArrayList;
import java.util.Base64;
import java.util.HashSet;
import java.util.Iterator;
+import java.util.List;
import java.util.Set;
+import java.util.concurrent.atomic.AtomicInteger;
import org.junit.Test;
import static org.assertj.core.api.Assertions.assertThat;
@@ -31,7 +34,7 @@ public class UuidGeneratorImplTest {
private UuidGeneratorImpl underTest = new UuidGeneratorImpl();
@Test
- public void generate_returns_unique_values_without_common_initial_letter_given_more_than_one_milisecond_between_generate_calls() throws InterruptedException {
+ public void generate_returns_unique_values_without_common_initial_letter_given_more_than_one_millisecond_between_generate_calls() throws InterruptedException {
Base64.Encoder encoder = Base64.getEncoder();
int count = 30;
Set<String> uuids = new HashSet<>(count);
@@ -50,6 +53,33 @@ public class UuidGeneratorImplTest {
}
@Test
+ public void generate_concurrent_test() throws InterruptedException {
+ int rounds = 500;
+ List<byte[]> uuids1 = new ArrayList<>(rounds);
+ List<byte[]> uuids2 = new ArrayList<>(rounds);
+ Thread t1 = new Thread(() -> {
+ for (int i = 0; i < rounds; i++) {
+ uuids1.add(underTest.generate());
+ }
+ });
+ Thread t2 = new Thread(() -> {
+ for (int i = 0; i < rounds; i++) {
+ uuids2.add(underTest.generate());
+ }
+ });
+ t1.start();
+ t2.start();
+ t1.join();
+ t2.join();
+
+ Base64.Encoder encoder = Base64.getEncoder();
+ Set<String> uuids = new HashSet<>(rounds * 2);
+ uuids1.forEach(bytes -> uuids.add(encoder.encodeToString(bytes)));
+ uuids2.forEach(bytes -> uuids.add(encoder.encodeToString(bytes)));
+ assertThat(uuids).hasSize(rounds * 2);
+ }
+
+ @Test
public void generate_from_FixedBase_returns_unique_values_where_only_last_4_later_letter_change() {
Base64.Encoder encoder = Base64.getEncoder();
int count = 100_000;
@@ -68,4 +98,33 @@ public class UuidGeneratorImplTest {
assertThat(iterator.next()).startsWith(base);
}
}
+
+ @Test
+ public void generate_from_FixedBase_concurrent_test() throws InterruptedException {
+ UuidGenerator.WithFixedBase withFixedBase = underTest.withFixedBase();
+ int rounds = 500;
+ List<byte[]> uuids1 = new ArrayList<>(rounds);
+ List<byte[]> uuids2 = new ArrayList<>(rounds);
+ AtomicInteger cnt = new AtomicInteger();
+ Thread t1 = new Thread(() -> {
+ for (int i = 0; i < rounds; i++) {
+ uuids1.add(withFixedBase.generate(cnt.getAndIncrement()));
+ }
+ });
+ Thread t2 = new Thread(() -> {
+ for (int i = 0; i < rounds; i++) {
+ uuids2.add(withFixedBase.generate(cnt.getAndIncrement()));
+ }
+ });
+ t1.start();
+ t2.start();
+ t1.join();
+ t2.join();
+
+ Base64.Encoder encoder = Base64.getEncoder();
+ Set<String> uuids = new HashSet<>(rounds * 2);
+ uuids1.forEach(bytes -> uuids.add(encoder.encodeToString(bytes)));
+ uuids2.forEach(bytes -> uuids.add(encoder.encodeToString(bytes)));
+ assertThat(uuids).hasSize(rounds * 2);
+ }
}
diff --git a/sonar-db/src/main/java/org/sonar/db/ce/CeActivityDao.java b/sonar-db/src/main/java/org/sonar/db/ce/CeActivityDao.java
index 5a7cada22da..ec07a732ff8 100644
--- a/sonar-db/src/main/java/org/sonar/db/ce/CeActivityDao.java
+++ b/sonar-db/src/main/java/org/sonar/db/ce/CeActivityDao.java
@@ -24,7 +24,6 @@ import java.util.Collections;
import java.util.List;
import java.util.Set;
import javax.annotation.Nullable;
-import org.apache.ibatis.session.RowBounds;
import org.sonar.api.utils.System2;
import org.sonar.db.Dao;
import org.sonar.db.DbSession;
@@ -46,15 +45,13 @@ public class CeActivityDao implements Dao {
public void insert(DbSession dbSession, CeActivityDto dto) {
dto.setCreatedAt(system2.now());
dto.setUpdatedAt(system2.now());
- dto.setIsLast(false);
- mapper(dbSession).insert(dto);
+ dto.setIsLast(dto.getStatus() != CeActivityDto.Status.CANCELED);
- List<String> uuids = mapper(dbSession).selectUuidsOfRecentlyCreatedByIsLastKey(dto.getIsLastKey(), new RowBounds(0, 1));
- // should never be empty, as a row was just inserted!
- if (!uuids.isEmpty()) {
- mapper(dbSession).updateIsLastToFalseForLastKey(dto.getIsLastKey(), dto.getUpdatedAt());
- mapper(dbSession).updateIsLastToTrueForUuid(uuids.get(0), dto.getUpdatedAt());
+ CeActivityMapper ceActivityMapper = mapper(dbSession);
+ if (dto.getIsLast()) {
+ ceActivityMapper.updateIsLastToFalseForLastKey(dto.getIsLastKey(), dto.getUpdatedAt());
}
+ ceActivityMapper.insert(dto);
}
public List<CeActivityDto> selectOlderThan(DbSession dbSession, long beforeDate) {
diff --git a/sonar-db/src/main/java/org/sonar/db/ce/CeActivityMapper.java b/sonar-db/src/main/java/org/sonar/db/ce/CeActivityMapper.java
index ea5d9e9c885..07015f5335f 100644
--- a/sonar-db/src/main/java/org/sonar/db/ce/CeActivityMapper.java
+++ b/sonar-db/src/main/java/org/sonar/db/ce/CeActivityMapper.java
@@ -23,12 +23,9 @@ import java.util.List;
import javax.annotation.CheckForNull;
import javax.annotation.Nullable;
import org.apache.ibatis.annotations.Param;
-import org.apache.ibatis.session.RowBounds;
public interface CeActivityMapper {
- List<String> selectUuidsOfRecentlyCreatedByIsLastKey(@Param("isLastKey") String isLastKey, RowBounds rowBounds);
-
@CheckForNull
CeActivityDto selectByUuid(@Param("uuid") String uuid);
@@ -44,7 +41,5 @@ public interface CeActivityMapper {
void updateIsLastToFalseForLastKey(@Param("isLastKey") String isLastKey, @Param("updatedAt") long updatedAt);
- void updateIsLastToTrueForUuid(@Param("uuid") String uuid, @Param("updatedAt") long updatedAt);
-
void deleteByUuids(@Param("uuids") List<String> uuids);
}
diff --git a/sonar-db/src/main/resources/org/sonar/db/ce/CeActivityMapper.xml b/sonar-db/src/main/resources/org/sonar/db/ce/CeActivityMapper.xml
index c0281f1b9d9..c4226b8efb2 100644
--- a/sonar-db/src/main/resources/org/sonar/db/ce/CeActivityMapper.xml
+++ b/sonar-db/src/main/resources/org/sonar/db/ce/CeActivityMapper.xml
@@ -44,14 +44,6 @@
where ca.uuid=#{uuid}
</select>
- <select id="selectUuidsOfRecentlyCreatedByIsLastKey" parameterType="String" resultType="String">
- select uuid
- from ce_activity
- where is_last_key=#{isLastKey}
- and status &lt;&gt; 'CANCELED'
- order by id desc
- </select>
-
<select id="selectByQuery" parameterType="map" resultType="org.sonar.db.ce.CeActivityDto">
SELECT
<include refid="columns"/>
@@ -181,13 +173,6 @@
where is_last=${_true} and is_last_key=#{isLastKey}
</update>
- <update id="updateIsLastToTrueForUuid" parameterType="map">
- update ce_activity
- set is_last=${_true},
- updated_at=#{updatedAt,jdbcType=BIGINT}
- where uuid=#{uuid}
- </update>
-
<delete id="deleteByUuids" parameterType="string">
delete
from ce_activity