Browse Source

update cn.reghao.jutil.jdk.store package

reghao 2 years ago
parent
commit
3bc24ebb27

+ 17 - 0
jdk/src/main/java/cn/reghao/jutil/jdk/store/LoadBalancer.java

@@ -0,0 +1,17 @@
+package cn.reghao.jutil.jdk.store;
+
+import java.util.Comparator;
+import java.util.List;
+
+/**
+ * @author reghao
+ * @date 2022-03-22 13:53:08
+ */
+public class LoadBalancer {
+    public StoreDir getStoreDir(long fileSize) {
+        LocalStore localStore = LocalStores.getMaxStore(fileSize);
+        List<StoreDir> subDirs = LocalStores.getSubDirs(localStore.getDiskDir());
+        subDirs.sort(Comparator.comparingInt(StoreDir::getTotal));
+        return subDirs.get(0);
+    }
+}

+ 72 - 0
jdk/src/main/java/cn/reghao/jutil/jdk/store/LocalStore.java

@@ -0,0 +1,72 @@
+package cn.reghao.jutil.jdk.store;
+
+import java.math.BigDecimal;
+import java.math.RoundingMode;
+import java.util.concurrent.atomic.AtomicLong;
+
+/**
+ * 表示一块磁盘
+ *
+ * @author reghao
+ * @date 2022-05-23 15:00:59
+ */
+public class LocalStore {
+    private final String logicalDisk;
+    // disk mounted directory
+    private final String diskDir;
+    private final long total;
+    private final AtomicLong available;
+    private final long max;
+
+    public LocalStore(String logicalDisk, String diskDir, long total, long available, double maxPercent) {
+        this.logicalDisk = logicalDisk;
+        this.diskDir = diskDir;
+        this.total = total;
+        this.available = new AtomicLong(available);
+        BigDecimal bigDecimal1 = new BigDecimal(total*10);
+        BigDecimal bigDecimal2 = new BigDecimal(maxPercent*10);
+        BigDecimal result = bigDecimal1.divide(bigDecimal2, RoundingMode.DOWN);
+        this.max = result.longValue();
+    }
+
+    public String getLogicalDisk() {
+        return logicalDisk;
+    }
+
+    public String getDiskDir() {
+        return diskDir;
+    }
+
+    public long getTotal() {
+        return total;
+    }
+
+    public long getAvailable() {
+        return available.get();
+    }
+
+    public void setCurrentAvailable(long currentAvailable) {
+        available.getAndSet(currentAvailable);
+    }
+
+    @Override
+    public int hashCode() {
+        int result = 17;
+        result = result * 31 + diskDir.hashCode();
+        return result;
+    }
+
+    @Override
+    public boolean equals(Object other) {
+        if (other == this) {
+            return true;
+        }
+
+        if (other instanceof LocalStore) {
+            LocalStore o = (LocalStore) other;
+            return o.diskDir.equals(diskDir);
+        } else {
+            return false;
+        }
+    }
+}

+ 97 - 0
jdk/src/main/java/cn/reghao/jutil/jdk/store/LocalStores.java

@@ -0,0 +1,97 @@
+package cn.reghao.jutil.jdk.store;
+
+import java.io.File;
+import java.io.IOException;
+import java.nio.file.FileStore;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.*;
+
+/**
+ * @author reghao
+ * @date 2022-05-23 18:21:22
+ */
+public class LocalStores {
+    private static final Map<String, LocalStore> storeMap = new HashMap<>();
+    private static final Map<String, Map<String, StoreDir>> storeDirMap = new HashMap<>();
+
+    public static void init(List<String> diskDirs) throws IOException {
+        Map<String, String> map = new HashMap<>();
+        for (String diskDir : diskDirs) {
+            FileStore fileStore = Files.getFileStore(Path.of(diskDir));
+            String logicalDisk = fileStore.name();
+            String prevValue = map.putIfAbsent(logicalDisk, diskDir);
+            if (prevValue == null) {
+                long total = fileStore.getTotalSpace();
+                long available = fileStore.getUsableSpace();
+                LocalStore localStore = new LocalStore(logicalDisk, diskDir, total, available, 0.9);
+                storeMap.put(diskDir, localStore);
+                storeDirMap.computeIfAbsent(diskDir, k -> new HashMap<>());
+                createSubDirs(diskDir);
+            } else {
+                String msg = String.format("%s's mounted directory %s has already associated with %s", logicalDisk, diskDir, prevValue);
+                System.out.println(msg);
+            }
+        }
+    }
+
+    private static void createSubDirs(String diskDir) throws IOException {
+        int total = 128;
+        for (int i = 0; i < total; i++) {
+            for (int j = 0; j < total; j++) {
+                String baseDir = String.format("%s/%s/%s/", diskDir, i, j);
+                File dir = new File(baseDir);
+                if (!dir.exists() && !dir.mkdirs()) {
+                    String msg = String.format("create %s failed", dir);
+                    throw new IOException(msg);
+                }
+
+                storeDirMap.get(diskDir).put(baseDir, new StoreDir(baseDir));
+            }
+        }
+    }
+
+    public static void initStoreDirs(String diskDir, Map<String, Integer> map) {
+        Map<String, StoreDir> map1 = storeDirMap.get(diskDir);
+        if (map1 == null) {
+            return;
+        }
+
+        map.forEach((path, total) -> {
+            StoreDir storeDir = map1.get(path);
+            if (storeDir != null) {
+                storeDir.setTotal(total);
+            }
+        });
+    }
+
+    // TODO 优化算法, 处理异常
+    public static LocalStore getMaxStore(long size) {
+        Map<String, Long> map = new HashMap<>();
+        for (Map.Entry<String, LocalStore> entry : storeMap.entrySet()) {
+            String diskDir = entry.getKey();
+            LocalStore localStore = entry.getValue();
+            long currentAvailable = localStore.getAvailable() - size;
+            map.put(diskDir, currentAvailable);
+        }
+
+        List<String> diskDirs = new ArrayList<>();
+        // diskDirs 中的元素升序排列
+        map.entrySet().stream()
+                .sorted(Map.Entry.comparingByValue())
+                .forEachOrdered(b -> diskDirs.add(b.getKey()));
+
+        String maxDisk = diskDirs.get(diskDirs.size()-1);
+        LocalStore localStore = storeMap.get(maxDisk);
+        localStore.setCurrentAvailable(map.get(maxDisk));
+        return localStore;
+    }
+    
+    public static List<StoreDir> getSubDirs(String diskDir) {
+        return new ArrayList<>(storeDirMap.get(diskDir).values());
+    }
+
+    public static List<LocalStore> getLocalStores() {
+        return new ArrayList<>(storeMap.values());
+    }
+}

+ 37 - 0
jdk/src/main/java/cn/reghao/jutil/jdk/store/StoreDir.java

@@ -0,0 +1,37 @@
+package cn.reghao.jutil.jdk.store;
+
+import java.util.concurrent.atomic.AtomicInteger;
+
+/**
+ * @author reghao
+ * @date 2022-05-23 23:31:21
+ */
+public class StoreDir {
+    private final String baseDir;
+    private final AtomicInteger total;
+
+    public StoreDir(String baseDir) {
+        this.baseDir = baseDir;
+        this.total = new AtomicInteger(0);
+    }
+
+    public String getBaseDir() {
+        return baseDir;
+    }
+
+    public void setTotal(int total) {
+        this.total.setPlain(total);
+    }
+
+    public int getTotal() {
+        return total.get();
+    }
+
+    public void incr() {
+        this.total.incrementAndGet();
+    }
+
+    public void decr() {
+        this.total.decrementAndGet();
+    }
+}