Make new message UUIDs more URL encoding friendly
=, + and / require triplet encoding in URLs. Cleanup the base64 encoding string to use different characters. This only impacts newly created string, existing strings will continue to require a much longer encoding when sent in JSON messages from the REST API. Also strip leading 'A'. Most strings start with a run of 'A' due to the first few bytes of uuidPrefix always being 0. Avoid long runs of - in the resulting IDs by mixing the bits using the uuidPrefix as the salt for the mixer. Change-Id: I0a7da0aec071329c840447a0914d14118f2f20a4
This commit is contained in:
@@ -14,6 +14,7 @@
|
|||||||
|
|
||||||
package com.google.gerrit.server;
|
package com.google.gerrit.server;
|
||||||
|
|
||||||
|
import com.google.common.base.CharMatcher;
|
||||||
import com.google.gerrit.common.ChangeHooks;
|
import com.google.gerrit.common.ChangeHooks;
|
||||||
import com.google.gerrit.reviewdb.client.Change;
|
import com.google.gerrit.reviewdb.client.Change;
|
||||||
import com.google.gerrit.reviewdb.client.ChangeMessage;
|
import com.google.gerrit.reviewdb.client.ChangeMessage;
|
||||||
@@ -35,6 +36,7 @@ import com.google.gerrit.server.patch.PatchSetInfoFactory;
|
|||||||
import com.google.gerrit.server.patch.PatchSetInfoNotAvailableException;
|
import com.google.gerrit.server.patch.PatchSetInfoNotAvailableException;
|
||||||
import com.google.gerrit.server.project.InvalidChangeOperationException;
|
import com.google.gerrit.server.project.InvalidChangeOperationException;
|
||||||
import com.google.gerrit.server.project.NoSuchChangeException;
|
import com.google.gerrit.server.project.NoSuchChangeException;
|
||||||
|
import com.google.gerrit.server.util.IdGenerator;
|
||||||
import com.google.gwtorm.server.AtomicUpdate;
|
import com.google.gwtorm.server.AtomicUpdate;
|
||||||
import com.google.gwtorm.server.OrmConcurrencyException;
|
import com.google.gwtorm.server.OrmConcurrencyException;
|
||||||
import com.google.gwtorm.server.OrmException;
|
import com.google.gwtorm.server.OrmException;
|
||||||
@@ -66,7 +68,6 @@ import java.util.Set;
|
|||||||
import java.util.regex.Matcher;
|
import java.util.regex.Matcher;
|
||||||
|
|
||||||
public class ChangeUtil {
|
public class ChangeUtil {
|
||||||
|
|
||||||
private static final Logger log = LoggerFactory.getLogger(ChangeUtil.class);
|
private static final Logger log = LoggerFactory.getLogger(ChangeUtil.class);
|
||||||
|
|
||||||
private static int uuidPrefix;
|
private static int uuidPrefix;
|
||||||
@@ -83,7 +84,12 @@ public class ChangeUtil {
|
|||||||
public static String messageUUID(final ReviewDb db) throws OrmException {
|
public static String messageUUID(final ReviewDb db) throws OrmException {
|
||||||
final byte[] raw = new byte[8];
|
final byte[] raw = new byte[8];
|
||||||
fill(raw, db);
|
fill(raw, db);
|
||||||
return Base64.encodeBytes(raw);
|
|
||||||
|
// Make the resulting base64 string more URL friendly.
|
||||||
|
return CharMatcher.is('A').trimLeadingFrom(
|
||||||
|
CharMatcher.is('=').trimTrailingFrom(Base64.encodeBytes(raw)))
|
||||||
|
.replace('+', '.')
|
||||||
|
.replace('/', '-');
|
||||||
}
|
}
|
||||||
|
|
||||||
private static synchronized void fill(byte[] raw, ReviewDb db)
|
private static synchronized void fill(byte[] raw, ReviewDb db)
|
||||||
@@ -93,7 +99,7 @@ public class ChangeUtil {
|
|||||||
uuidSeq = Integer.MAX_VALUE;
|
uuidSeq = Integer.MAX_VALUE;
|
||||||
}
|
}
|
||||||
NB.encodeInt32(raw, 0, uuidPrefix);
|
NB.encodeInt32(raw, 0, uuidPrefix);
|
||||||
NB.encodeInt32(raw, 4, uuidSeq--);
|
NB.encodeInt32(raw, 4, IdGenerator.mix(uuidPrefix, uuidSeq--));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void touch(final Change change, ReviewDb db)
|
public static void touch(final Change change, ReviewDb db)
|
||||||
|
|||||||
@@ -43,13 +43,13 @@ public class IdGenerator {
|
|||||||
|
|
||||||
/** Produce the next identifier. */
|
/** Produce the next identifier. */
|
||||||
public int next() {
|
public int next() {
|
||||||
return mix(gen.getAndIncrement());
|
return mix(salt, gen.getAndIncrement());
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final int salt = 0x9e3779b9;
|
private static final int salt = 0x9e3779b9;
|
||||||
|
|
||||||
/** A very simple bit permutation to mask a simple incrementer. */
|
/** A very simple bit permutation to mask a simple incrementer. */
|
||||||
static int mix(final int in) {
|
public static int mix(final int salt, final int in) {
|
||||||
short v0 = hi16(in);
|
short v0 = hi16(in);
|
||||||
short v1 = lo16(in);
|
short v1 = lo16(in);
|
||||||
v0 += ((v1 << 2) + 0 ^ v1) + (salt ^ (v1 >>> 3)) + 1;
|
v0 += ((v1 << 2) + 0 ^ v1) + (salt ^ (v1 >>> 3)) + 1;
|
||||||
|
|||||||
Reference in New Issue
Block a user