Remove sequence-based UID generation for messages
Unique identifiers for ChangeMessages and PatchLineComments were generated using a seed from a database sequence, mixed together with IdGenerator. In the spirit of killing ReviewDb, use a cryptographically secure pseudorandom number generator to generate these IDs instead. Follow the same "xxxxxxxx_xxxxxxxx" format so IDs look similar. I suppose the goal of the sequence-based approach was to decrease the chance of collision by including a piece of state in each ID that is guaranteed unique across the server. However, the chance of collision for any 8-byte identifier can never be less than 1/2^64 no matter what implementation we choose. By definition a cryptographically secure PRNG generates random data that is evenly distributed across the entire byte space, so the PRNG implementation also has a 1/2^64 chance of collisions; we're just swapping one rare-collision implementation with another. (This assumes no bugs or weaknesses in the PRNG implementation, but with all due respect to Shawn, I don't think the JDK's PRNG is any more likely to have collision-introducing flaws than our hand-written IdGenerator.) This change actually has no effect on ChangeMessage IDs that are stored in or read from NoteDb, because ChangeNotesParser always populates the ChangeMessage UUID field with the SHA-1 in the notes graph of the commit that introduced the message; ReviewDb UUIDs are simply discarded. The messageUuid method is still called during creation because of the implementation details of ChangeMessagesUtil, but that ID is not used for storage. This change does have an effect on the IDs generated for PatchLineComments, which also use messageUuid for their IDs, despite the somewhat confusing fact that the ReviewDb interface implies the ID is just for ChangeMessages. While we're in there, rename the method to messageUuid to match the Google Java Style Guide for camelCase names. Change-Id: I7d157b9e8f87b41d4e7a146b705012863c27d42e
This commit is contained in:
@@ -17,10 +17,8 @@ package com.google.gerrit.server;
|
||||
import static java.util.Comparator.comparingInt;
|
||||
|
||||
import com.google.common.collect.Ordering;
|
||||
import com.google.common.io.BaseEncoding;
|
||||
import com.google.gerrit.reviewdb.client.PatchSet;
|
||||
import com.google.gerrit.reviewdb.server.ReviewDb;
|
||||
import com.google.gerrit.server.util.IdGenerator;
|
||||
import com.google.gwtorm.server.OrmException;
|
||||
import com.google.inject.Singleton;
|
||||
|
||||
import org.eclipse.jgit.lib.Ref;
|
||||
@@ -28,14 +26,15 @@ import org.eclipse.jgit.lib.RefDatabase;
|
||||
import org.eclipse.jgit.lib.Repository;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.security.SecureRandom;
|
||||
import java.util.Map;
|
||||
import java.util.Random;
|
||||
|
||||
@Singleton
|
||||
public class ChangeUtil {
|
||||
private static final Object uuidLock = new Object();
|
||||
private static final int SEED = 0x2418e6f9;
|
||||
private static int uuidPrefix;
|
||||
private static int uuidSeq;
|
||||
private static final Random UUID_RANDOM = new SecureRandom();
|
||||
private static final BaseEncoding UUID_ENCODING =
|
||||
BaseEncoding.base16().lowerCase();
|
||||
|
||||
private static final int SUBJECT_MAX_LENGTH = 80;
|
||||
private static final String SUBJECT_CROP_APPENDIX = "...";
|
||||
@@ -44,28 +43,12 @@ public class ChangeUtil {
|
||||
public static final Ordering<PatchSet> PS_ID_ORDER =
|
||||
Ordering.from(comparingInt(PatchSet::getPatchSetId));
|
||||
|
||||
/**
|
||||
* Generate a new unique identifier for change message entities.
|
||||
*
|
||||
* @param db the database connection, used to increment the change message
|
||||
* allocation sequence.
|
||||
* @return the new unique identifier.
|
||||
* @throws OrmException the database couldn't be incremented.
|
||||
*/
|
||||
public static String messageUUID(ReviewDb db) throws OrmException {
|
||||
int p;
|
||||
int s;
|
||||
synchronized (uuidLock) {
|
||||
if (uuidSeq == 0) {
|
||||
uuidPrefix = db.nextChangeMessageId();
|
||||
uuidSeq = Integer.MAX_VALUE;
|
||||
}
|
||||
p = uuidPrefix;
|
||||
s = uuidSeq--;
|
||||
}
|
||||
String u = IdGenerator.format(IdGenerator.mix(SEED, p));
|
||||
String l = IdGenerator.format(IdGenerator.mix(p, s));
|
||||
return u + '_' + l;
|
||||
/** @return a new unique identifier for change message entities. */
|
||||
public static String messageUuid() {
|
||||
byte[] buf = new byte[8];
|
||||
UUID_RANDOM.nextBytes(buf);
|
||||
return UUID_ENCODING.encode(buf, 0, 4) + '_'
|
||||
+ UUID_ENCODING.encode(buf, 4, 4);
|
||||
}
|
||||
|
||||
public static PatchSet.Id nextPatchSetId(Map<String, Ref> allRefs,
|
||||
|
||||
Reference in New Issue
Block a user