ID range generation
authorMathieu Baudier <mbaudier@argeo.org>
Sat, 24 Sep 2022 10:39:20 +0000 (12:39 +0200)
committerMathieu Baudier <mbaudier@argeo.org>
Sat, 24 Sep 2022 10:39:20 +0000 (12:39 +0200)
org.argeo.app.api/src/org/argeo/app/api/IdRange.java

index d96c789b2ecba81cf0862347ae13b155a7f02c32..e47eb5e5cfc42ed6c11371d00e5de2ff603ca622 100644 (file)
@@ -1,9 +1,20 @@
 package org.argeo.app.api;
 
 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 {
 /** 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;
        private final long min;
+       /** included */
        private final long max;
 
        public IdRange(long min, long max) {
        private final long max;
 
        public IdRange(long min, long max) {
@@ -23,6 +34,68 @@ public class IdRange {
                return max;
        }
 
                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<IdRange> randomRanges10000(int count, Set<IdRange> forbiddenRanges) {
+               Set<IdRange> 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<IdRange> 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");
        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++;
                }
                                break exp;
                        exp++;
                }
-               System.out.println(exp);
+//             System.out.println(exp);
 
                long max = minPow10 + pow10(exp) - 1;
                return max;
 
                long max = minPow10 + pow10(exp) - 1;
                return max;