From 6c865d26fd557c232ad8372bda9de2eecc25d65e Mon Sep 17 00:00:00 2001 From: teddy Date: Thu, 12 Feb 2026 18:18:44 +0900 Subject: [PATCH] =?UTF-8?q?=EC=9E=84=EC=8B=9C=ED=8C=8C=EC=9D=BC=EC=83=9D?= =?UTF-8?q?=EC=84=B1=20=EC=86=8C=ED=94=84=ED=8A=B8=EB=A7=81=ED=81=AC?= =?UTF-8?q?=EC=97=90=EC=84=9C=20=ED=95=98=EB=93=9C=EB=A7=81=ED=81=AC?= =?UTF-8?q?=EB=A1=9C=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../model/service/TmpDatasetService.java | 65 ++++++++++++++----- 1 file changed, 50 insertions(+), 15 deletions(-) diff --git a/src/main/java/com/kamco/cd/training/model/service/TmpDatasetService.java b/src/main/java/com/kamco/cd/training/model/service/TmpDatasetService.java index 7f04c98..918bc77 100644 --- a/src/main/java/com/kamco/cd/training/model/service/TmpDatasetService.java +++ b/src/main/java/com/kamco/cd/training/model/service/TmpDatasetService.java @@ -18,7 +18,7 @@ public class TmpDatasetService { public String buildTmpDatasetSymlink(String uid, List datasetUids) throws IOException { - log.info("========== buildTmpDatasetSymlink START =========="); + log.info("========== buildTmpDatasetHardlink START =========="); log.info("uid={}", uid); log.info("datasetUids={}", datasetUids); log.info("requestDir(raw)={}", requestDir); @@ -30,8 +30,9 @@ public class TmpDatasetService { log.info("BASE exists? {}", Files.isDirectory(BASE)); log.info("tmp={}", tmp); - long noDir = 0, scannedDirs = 0, regularFiles = 0, symlinksMade = 0; + long noDir = 0, scannedDirs = 0, regularFiles = 0, hardlinksMade = 0; + // tmp 디렉토리 준비 for (String type : List.of("train", "val")) { for (String part : List.of("input1", "input2", "label")) { Path dir = tmp.resolve(type).resolve(part); @@ -40,6 +41,27 @@ public class TmpDatasetService { } } + // 하드링크는 "같은 파일시스템"에서만 가능하므로 BASE/tmp가 같은 FS인지 미리 확인(권장) + try { + var baseStore = Files.getFileStore(BASE); + var tmpStore = Files.getFileStore(tmp.getParent()); // BASE/tmp + if (!baseStore.name().equals(tmpStore.name()) || !baseStore.type().equals(tmpStore.type())) { + throw new IOException( + "Hardlink requires same filesystem. baseStore=" + + baseStore.name() + + "(" + + baseStore.type() + + "), tmpStore=" + + tmpStore.name() + + "(" + + tmpStore.type() + + ")"); + } + } catch (Exception e) { + // FileStore 비교가 환경마다 애매할 수 있어서, 여기서는 경고만 주고 실제 createLink에서 최종 판단하게 둘 수도 있음. + log.warn("FileStore check skipped/failed (will rely on createLink): {}", e.toString()); + } + for (String id : datasetUids) { Path srcRoot = BASE.resolve(id); log.info("---- dataset id={} srcRoot={} exists? {}", id, srcRoot, Files.isDirectory(srcRoot)); @@ -70,18 +92,21 @@ public class TmpDatasetService { String dstName = id + "__" + f.getFileName(); Path dst = tmp.resolve(type).resolve(part).resolve(dstName); + // dst가 남아있으면 삭제(심볼릭링크든 파일이든) + if (Files.exists(dst) || Files.isSymbolicLink(dst)) { + Files.delete(dst); + log.debug("deleted existing: {}", dst); + } + try { - if (Files.exists(dst) || Files.isSymbolicLink(dst)) { - Files.delete(dst); - log.debug("deleted existing: {}", dst); - } - - Files.createSymbolicLink(dst, f.toAbsolutePath()); - symlinksMade++; - log.debug("created symlink: {} -> {}", dst, f.toAbsolutePath()); - - } catch (Exception e) { - log.error("FAILED create symlink: {} -> {}", dst, f.toAbsolutePath(), e); + // 하드링크 생성 (dst가 새 파일로 생기지만 inode는 f와 동일) + Files.createLink(dst, f); + hardlinksMade++; + log.debug("created hardlink: {} => {}", dst, f); + } catch (IOException e) { + // 여기서 바로 실패시키면 “tmp는 만들었는데 내용은 0개” 같은 상태를 방지할 수 있음 + log.error("FAILED create hardlink: {} => {}", dst, f, e); + throw e; } } } @@ -89,13 +114,23 @@ public class TmpDatasetService { } } + if (hardlinksMade == 0) { + throw new IOException( + "No hardlinks created. regularFiles=" + + regularFiles + + ", scannedDirs=" + + scannedDirs + + ", noDir=" + + noDir); + } + log.info("tmp dataset created: {}", tmp); log.info( - "summary: scannedDirs={}, noDir={}, regularFiles={}, symlinksMade={}", + "summary: scannedDirs={}, noDir={}, regularFiles={}, hardlinksMade={}", scannedDirs, noDir, regularFiles, - symlinksMade); + hardlinksMade); return uid; }