Guest User

Untitled

a guest
Feb 22nd, 2018
80
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 2.43 KB | None | 0 0
  1. /**
  2. * Fancy ID generator that creates 20-character string identifiers with the following properties:
  3. *
  4. * 1. They're based on timestamp so that they sort *after* any existing ids.
  5. * 2. They contain 72-bits of random data after the timestamp so that IDs won't collide with other clients' IDs.
  6. * 3. They sort *lexicographically* (so the timestamp is converted to characters that will sort properly).
  7. * 4. They're monotonically increasing. Even if you generate more than one in the same timestamp, the
  8. * latter ones will sort after the former ones. We do this by using the previous random bits
  9. * but "incrementing" them by 1 (only in the case of a timestamp collision).
  10. */
  11. public class FirebasePushIDGenerator {
  12. // Modeled after base64 web-safe chars, but ordered by ASCII.
  13. private final static String PUSH_CHARS = "-0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz";
  14.  
  15. // Timestamp of last push, used to prevent local collisions if you push twice in one ms.
  16. private static long lastPushTime = 0L;
  17.  
  18. // We generate 72-bits of randomness which get turned into 12 characters and appended to the
  19. // timestamp to prevent collisions with other clients. We store the last characters we
  20. // generated because in the event of a collision, we'll use those same characters except
  21. // "incremented" by one.
  22. private static int[] lastRandChars = new int[72];
  23.  
  24. public static String generatePushId() {
  25. long now = System.currentTimeMillis();
  26. boolean duplicateTime = (now == lastPushTime);
  27. lastPushTime = now;
  28.  
  29. char[] timeStampChars = new char[8];
  30. for (int i = 7; i >= 0; i--) {
  31. final Long module = now % 64;
  32. timeStampChars[i] = PUSH_CHARS.charAt(module.intValue());
  33. now = (long) Math.floor(now / 64);
  34. }
  35. if (now != 0) {
  36. throw new AssertionError("We should have converted the entire timestamp.");
  37. }
  38.  
  39. String id = new String(timeStampChars);
  40.  
  41. if (!duplicateTime) {
  42. for (int i = 0; i < 12; i++) {
  43. final Double times = Math.random() * 64;
  44. lastRandChars[i] = (int) Math.floor(times.intValue());
  45. }
  46. } else {
  47. // If the timestamp hasn't changed since last push, use the same random number, except incremented by 1.
  48. int i = 0;
  49. for (i = 11; i >= 0 && lastRandChars[i] == 63; i--) {
  50. lastRandChars[i] = 0;
  51. }
  52. lastRandChars[i]++;
  53. }
  54. for (int i = 0; i < 12; i++) {
  55. id += PUSH_CHARS.charAt(lastRandChars[i]);
  56. }
  57. if (id.length() != 20) {
  58. throw new AssertionError("Length should be 20.");
  59. }
  60.  
  61. return id;
  62. };
  63.  
  64. }
Add Comment
Please, Sign In to add comment