From: Mathieu Baudier Date: Sat, 24 Sep 2022 10:39:20 +0000 (+0200) Subject: ID range generation X-Git-Tag: v2.3.8~29 X-Git-Url: https://git.argeo.org/?p=gpl%2Fargeo-suite.git;a=commitdiff_plain;h=68e87a1f35f88460fafe476521a6e5fa7f2fd22b ID range generation --- diff --git a/org.argeo.app.api/src/org/argeo/app/api/IdRange.java b/org.argeo.app.api/src/org/argeo/app/api/IdRange.java index d96c789..e47eb5e 100644 --- a/org.argeo.app.api/src/org/argeo/app/api/IdRange.java +++ b/org.argeo.app.api/src/org/argeo/app/api/IdRange.java @@ -1,9 +1,20 @@ package org.argeo.app.api; +import java.util.HashSet; +import java.util.Set; +import java.util.concurrent.ThreadLocalRandom; + /** A range of numerical IDs (typically numerical uid or gid). */ public class IdRange { + // see https://systemd.io/UIDS-GIDS/#special-distribution-uid-ranges + final static long MIN_INCLUDED = Long.parseUnsignedLong("66000"); + final static long MAX_EXCLUDED = Long.parseUnsignedLong("4294967294"); + // We use long as a de facto unsigned int + + /** included */ private final long min; + /** included */ private final long max; public IdRange(long min, long max) { @@ -23,6 +34,68 @@ public class IdRange { return max; } + @Override + public int hashCode() { + return (int) min; + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof IdRange idRange) { + return min == idRange.min && max == idRange.max; + } else + return false; + } + + @Override + public String toString() { + return "[" + Long.toUnsignedString(min) + "," + Long.toUnsignedString(max) + "]"; + } + + /* + * RANGE GENERATION + */ + public static synchronized Set randomRanges10000(int count, Set forbiddenRanges) { + Set res = new HashSet<>(); + + for (int i = 0; i < count; i++) { + IdRange newRange = null; + do { + newRange = randomRange10000(); + } while (overlap(newRange, res) || overlap(newRange, forbiddenRanges)); + res.add(newRange); + } + return res; + } + + public static synchronized IdRange randomRange10000() { + // TODO make it more generic + long minPred = 7l; + long maxPred = 429496l; + + long rand = ThreadLocalRandom.current().nextLong(minPred, maxPred); + long min = rand * 10000l; + return new IdRange(min); + } + + public static boolean overlap(IdRange idRange, Set idRanges) { + for (IdRange other : idRanges) { + if (overlap(idRange, other)) + return true; + } + return false; + } + + public static boolean overlap(IdRange idRange, IdRange other) { + // see + // https://stackoverflow.com/questions/3269434/whats-the-most-efficient-way-to-test-if-two-ranges-overlap + return idRange.min <= other.max && other.min <= idRange.max; + } + + /* + * UTILITIES + */ + private static long maxFromMinPow10(long minPow10) { if ((minPow10 % 100) != 0) { throw new IllegalArgumentException(minPow10 + " must at least ends with two zeroes"); @@ -33,7 +106,7 @@ public class IdRange { break exp; exp++; } - System.out.println(exp); +// System.out.println(exp); long max = minPow10 + pow10(exp) - 1; return max;