임시파일생성 소프트링크에서 하드링크로 변경
This commit is contained in:
@@ -18,7 +18,7 @@ public class TmpDatasetService {
|
||||
|
||||
public String buildTmpDatasetSymlink(String uid, List<String> 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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user