Compare commits
10 Commits
3da4b73c59
...
feat/train
| Author | SHA1 | Date | |
|---|---|---|---|
| 71a8b45097 | |||
| 219e17e8ba | |||
| a9260c17f4 | |||
| b546e053b6 | |||
| a66b25dda5 | |||
| bc67753b99 | |||
| 5dc817ecad | |||
| 8043e1a41a | |||
| 98e3c35d9a | |||
| d48e96ba82 |
@@ -144,7 +144,7 @@ public class FileManagerApiController {
|
|||||||
})
|
})
|
||||||
@GetMapping("/model-path/{modelUuid}")
|
@GetMapping("/model-path/{modelUuid}")
|
||||||
public ApiResponseDto<FileManagerDto.ModelFilePathRes> getModelFilePath(
|
public ApiResponseDto<FileManagerDto.ModelFilePathRes> getModelFilePath(
|
||||||
@Parameter(description = "모델 UUID", example = "123e4567-e89b-12d3-a456-426614174000")
|
@Parameter(description = "모델 UUID", example = "df284755-c0b7-4070-bfee-ef554e8d0fe4")
|
||||||
@PathVariable
|
@PathVariable
|
||||||
UUID modelUuid) {
|
UUID modelUuid) {
|
||||||
|
|
||||||
@@ -170,7 +170,7 @@ public class FileManagerApiController {
|
|||||||
})
|
})
|
||||||
@GetMapping("/dataset-path/{datasetUuid}")
|
@GetMapping("/dataset-path/{datasetUuid}")
|
||||||
public ApiResponseDto<FileManagerDto.DatasetFilePathRes> getDatasetFilePath(
|
public ApiResponseDto<FileManagerDto.DatasetFilePathRes> getDatasetFilePath(
|
||||||
@Parameter(description = "데이터셋 UUID", example = "123e4567-e89b-12d3-a456-426614174001")
|
@Parameter(description = "데이터셋 UUID", example = "037b09a0-b315-4e2e-b88d-b9011f9eaa15")
|
||||||
@PathVariable
|
@PathVariable
|
||||||
UUID datasetUuid) {
|
UUID datasetUuid) {
|
||||||
|
|
||||||
@@ -198,7 +198,7 @@ public class FileManagerApiController {
|
|||||||
public ApiResponseDto<FileManagerDto.DirectoryCapacityRes> checkDirectoryCapacity(
|
public ApiResponseDto<FileManagerDto.DirectoryCapacityRes> checkDirectoryCapacity(
|
||||||
@Parameter(
|
@Parameter(
|
||||||
description = "디렉토리 경로",
|
description = "디렉토리 경로",
|
||||||
example = "/home/kcomu/data/request/123e4567-e89b-12d3-a456-426614174001")
|
example = "/home/kcomu/data/request/037b09a0-b315-4e2e-b88d-b9011f9eaa15")
|
||||||
@RequestParam
|
@RequestParam
|
||||||
String directoryPath) {
|
String directoryPath) {
|
||||||
|
|
||||||
@@ -233,4 +233,27 @@ public class FileManagerApiController {
|
|||||||
fileManagerService.getModelsExecutionStatus();
|
fileManagerService.getModelsExecutionStatus();
|
||||||
return ApiResponseDto.ok(response);
|
return ApiResponseDto.ok(response);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Operation(
|
||||||
|
summary = "저장공간 정보 조회",
|
||||||
|
description =
|
||||||
|
"/home/kcomu/data 경로의 사용 중인 용량, 전체 디스크 용량, 남은 저장공간을 조회합니다. "
|
||||||
|
+ "파라미터 없이 호출하면 자동으로 /home/kcomu/data 경로 정보를 반환합니다.")
|
||||||
|
@ApiResponses(
|
||||||
|
value = {
|
||||||
|
@ApiResponse(
|
||||||
|
responseCode = "200",
|
||||||
|
description = "조회 성공",
|
||||||
|
content =
|
||||||
|
@Content(
|
||||||
|
mediaType = "application/json",
|
||||||
|
schema = @Schema(implementation = FileManagerDto.StorageSpaceRes.class))),
|
||||||
|
@ApiResponse(responseCode = "500", description = "서버 오류", content = @Content)
|
||||||
|
})
|
||||||
|
@GetMapping("/storage-space")
|
||||||
|
public ApiResponseDto<FileManagerDto.StorageSpaceRes> getStorageSpaceInfo() {
|
||||||
|
|
||||||
|
FileManagerDto.StorageSpaceRes response = fileManagerService.getStorageSpaceInfo();
|
||||||
|
return ApiResponseDto.ok(response);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -138,17 +138,17 @@ public class FileManagerDto {
|
|||||||
@AllArgsConstructor
|
@AllArgsConstructor
|
||||||
@Schema(description = "모델 파일 경로 정보 응답")
|
@Schema(description = "모델 파일 경로 정보 응답")
|
||||||
public static class ModelFilePathRes {
|
public static class ModelFilePathRes {
|
||||||
@Schema(description = "모델 UUID", example = "123e4567-e89b-12d3-a456-426614174000")
|
@Schema(description = "모델 UUID", example = "df284755-c0b7-4070-bfee-ef554e8d0fe4")
|
||||||
private String modelUuid;
|
private String modelUuid;
|
||||||
|
|
||||||
@Schema(
|
@Schema(
|
||||||
description = "요청 경로 (심볼릭 링크 디렉토리)",
|
description = "요청 경로 (심볼릭 링크 디렉토리)",
|
||||||
example = "/home/kcomu/data/tmp/123e4567-e89b-12d3-a456-426614174000")
|
example = "/home/kcomu/data/tmp/AE366F3076504FACBF12106986202AB5")
|
||||||
private String requestPath;
|
private String requestPath;
|
||||||
|
|
||||||
@Schema(
|
@Schema(
|
||||||
description = "응답 경로 (모델 결과 저장)",
|
description = "응답 경로 (모델 결과 저장)",
|
||||||
example = "/home/kcomu/data/response/123e4567-e89b-12d3-a456-426614174000")
|
example = "/home/kcomu/data/response/df284755-c0b7-4070-bfee-ef554e8d0fe4")
|
||||||
private String responsePath;
|
private String responsePath;
|
||||||
|
|
||||||
@Schema(description = "요청 경로 파일 목록")
|
@Schema(description = "요청 경로 파일 목록")
|
||||||
@@ -164,12 +164,12 @@ public class FileManagerDto {
|
|||||||
@AllArgsConstructor
|
@AllArgsConstructor
|
||||||
@Schema(description = "데이터셋 파일 경로 정보 응답")
|
@Schema(description = "데이터셋 파일 경로 정보 응답")
|
||||||
public static class DatasetFilePathRes {
|
public static class DatasetFilePathRes {
|
||||||
@Schema(description = "데이터셋 UUID", example = "123e4567-e89b-12d3-a456-426614174001")
|
@Schema(description = "데이터셋 UUID", example = "037b09a0-b315-4e2e-b88d-b9011f9eaa15")
|
||||||
private String datasetUuid;
|
private String datasetUuid;
|
||||||
|
|
||||||
@Schema(
|
@Schema(
|
||||||
description = "데이터셋 경로",
|
description = "데이터셋 경로",
|
||||||
example = "/home/kcomu/data/request/123e4567-e89b-12d3-a456-426614174001")
|
example = "/home/kcomu/data/request/037b09a0-b315-4e2e-b88d-b9011f9eaa15")
|
||||||
private String datasetPath;
|
private String datasetPath;
|
||||||
|
|
||||||
@Schema(description = "데이터셋 파일 목록")
|
@Schema(description = "데이터셋 파일 목록")
|
||||||
@@ -232,4 +232,47 @@ public class FileManagerDto {
|
|||||||
@Schema(description = "현재 실행 중인 모델 개수", example = "2")
|
@Schema(description = "현재 실행 중인 모델 개수", example = "2")
|
||||||
private Integer runningCount;
|
private Integer runningCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@Builder
|
||||||
|
@NoArgsConstructor
|
||||||
|
@AllArgsConstructor
|
||||||
|
@Schema(description = "저장공간 정보 응답 (남은 공간 포함)")
|
||||||
|
public static class StorageSpaceRes {
|
||||||
|
@Schema(description = "디렉토리 경로", example = "/home/kcomu/data")
|
||||||
|
private String directoryPath;
|
||||||
|
|
||||||
|
@Schema(description = "파일 개수", example = "1234")
|
||||||
|
private Integer fileCount;
|
||||||
|
|
||||||
|
@Schema(description = "디렉토리 개수", example = "56")
|
||||||
|
private Integer directoryCount;
|
||||||
|
|
||||||
|
@Schema(description = "사용 중인 용량 (bytes)", example = "10485760000")
|
||||||
|
private Long usedSize;
|
||||||
|
|
||||||
|
@Schema(description = "사용 중인 용량 (읽기 쉬운 형식)", example = "9.77 GB")
|
||||||
|
private String usedSizeFormatted;
|
||||||
|
|
||||||
|
@Schema(description = "전체 디스크 용량 (bytes)", example = "1000000000000")
|
||||||
|
private Long totalDiskSpace;
|
||||||
|
|
||||||
|
@Schema(description = "전체 디스크 용량 (읽기 쉬운 형식)", example = "931.32 GB")
|
||||||
|
private String totalDiskSpaceFormatted;
|
||||||
|
|
||||||
|
@Schema(description = "남은 저장공간 (bytes)", example = "500000000000")
|
||||||
|
private Long freeSpace;
|
||||||
|
|
||||||
|
@Schema(description = "남은 저장공간 (읽기 쉬운 형식)", example = "465.66 GB")
|
||||||
|
private String freeSpaceFormatted;
|
||||||
|
|
||||||
|
@Schema(description = "사용 가능한 공간 (bytes)", example = "480000000000")
|
||||||
|
private Long usableSpace;
|
||||||
|
|
||||||
|
@Schema(description = "사용 가능한 공간 (읽기 쉬운 형식)", example = "447.03 GB")
|
||||||
|
private String usableSpaceFormatted;
|
||||||
|
|
||||||
|
@Schema(description = "디스크 사용률 (%)", example = "50.5")
|
||||||
|
private Double usagePercentage;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -57,15 +57,38 @@ public class FileManagerService {
|
|||||||
|
|
||||||
boolean recursive = request.getRecursive() != null && request.getRecursive();
|
boolean recursive = request.getRecursive() != null && request.getRecursive();
|
||||||
|
|
||||||
validatePath(targetPath);
|
// 경로 검증은 수행하되, 예외를 throw하지 않고 빈 데이터 반환
|
||||||
|
try {
|
||||||
|
validatePath(targetPath);
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
log.debug("유효하지 않은 경로: {}", targetPath);
|
||||||
|
return FileManagerDto.ListFilesRes.builder()
|
||||||
|
.directoryPath(targetPath)
|
||||||
|
.files(new ArrayList<>())
|
||||||
|
.totalCount(0)
|
||||||
|
.totalSize(0L)
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
Path directory = Paths.get(targetPath);
|
Path directory = Paths.get(targetPath);
|
||||||
if (!Files.exists(directory)) {
|
if (!Files.exists(directory)) {
|
||||||
throw new IllegalArgumentException("디렉토리가 존재하지 않습니다: " + targetPath);
|
log.debug("디렉토리가 존재하지 않습니다: {}", targetPath);
|
||||||
|
return FileManagerDto.ListFilesRes.builder()
|
||||||
|
.directoryPath(targetPath)
|
||||||
|
.files(new ArrayList<>())
|
||||||
|
.totalCount(0)
|
||||||
|
.totalSize(0L)
|
||||||
|
.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!Files.isDirectory(directory)) {
|
if (!Files.isDirectory(directory)) {
|
||||||
throw new IllegalArgumentException("디렉토리 경로가 아닙니다: " + targetPath);
|
log.debug("디렉토리 경로가 아닙니다: {}", targetPath);
|
||||||
|
return FileManagerDto.ListFilesRes.builder()
|
||||||
|
.directoryPath(targetPath)
|
||||||
|
.files(new ArrayList<>())
|
||||||
|
.totalCount(0)
|
||||||
|
.totalSize(0L)
|
||||||
|
.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
List<FileManagerDto.FileInfo> files = new ArrayList<>();
|
List<FileManagerDto.FileInfo> files = new ArrayList<>();
|
||||||
@@ -106,8 +129,13 @@ public class FileManagerService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
log.error("파일 목록 조회 중 오류 발생: {}", targetPath, e);
|
log.debug("파일 목록 조회 중 오류 발생: {}", targetPath, e);
|
||||||
throw new RuntimeException("파일 목록 조회에 실패했습니다: " + e.getMessage());
|
return FileManagerDto.ListFilesRes.builder()
|
||||||
|
.directoryPath(targetPath)
|
||||||
|
.files(new ArrayList<>())
|
||||||
|
.totalCount(0)
|
||||||
|
.totalSize(0L)
|
||||||
|
.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
return FileManagerDto.ListFilesRes.builder()
|
return FileManagerDto.ListFilesRes.builder()
|
||||||
@@ -132,11 +160,18 @@ public class FileManagerService {
|
|||||||
|
|
||||||
for (String filePath : request.getFilePaths()) {
|
for (String filePath : request.getFilePaths()) {
|
||||||
try {
|
try {
|
||||||
validatePath(filePath);
|
try {
|
||||||
|
validatePath(filePath);
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
log.debug("유효하지 않은 경로: {}", filePath);
|
||||||
|
failedFiles.add(filePath + " (유효하지 않은 경로)");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
Path path = Paths.get(filePath);
|
Path path = Paths.get(filePath);
|
||||||
|
|
||||||
if (!Files.exists(path)) {
|
if (!Files.exists(path)) {
|
||||||
log.warn("삭제하려는 파일이 존재하지 않습니다: {}", filePath);
|
log.debug("삭제하려는 파일이 존재하지 않습니다: {}", filePath);
|
||||||
failedFiles.add(filePath + " (파일이 존재하지 않음)");
|
failedFiles.add(filePath + " (파일이 존재하지 않음)");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -164,7 +199,7 @@ public class FileManagerService {
|
|||||||
log.info("파일 삭제 성공: {}", filePath);
|
log.info("파일 삭제 성공: {}", filePath);
|
||||||
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
log.error("파일 삭제 실패: {}", filePath, e);
|
log.debug("파일 삭제 실패: {}", filePath, e);
|
||||||
failedFiles.add(filePath + " (" + e.getMessage() + ")");
|
failedFiles.add(filePath + " (" + e.getMessage() + ")");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -258,15 +293,33 @@ public class FileManagerService {
|
|||||||
* @return 모델 파일 경로 및 파일 목록
|
* @return 모델 파일 경로 및 파일 목록
|
||||||
*/
|
*/
|
||||||
public FileManagerDto.ModelFilePathRes getModelFilePath(UUID modelUuid) {
|
public FileManagerDto.ModelFilePathRes getModelFilePath(UUID modelUuid) {
|
||||||
// tb_model_master 테이블에서 모델 존재 여부 확인
|
// tb_model_master 테이블에서 모델 조회
|
||||||
modelMngRepository
|
ModelMasterEntity model = modelMngRepository.findByUuid(modelUuid).orElse(null);
|
||||||
.findByUuid(modelUuid)
|
|
||||||
.orElseThrow(() -> new IllegalArgumentException("모델을 찾을 수 없습니다: " + modelUuid));
|
|
||||||
|
|
||||||
// request_path: symbolic_link_dir + model_uuid
|
// 모델이 존재하지 않으면 빈 데이터 반환
|
||||||
String requestPath = symbolicLinkDir + "/" + modelUuid;
|
if (model == null) {
|
||||||
|
return FileManagerDto.ModelFilePathRes.builder()
|
||||||
|
.modelUuid(modelUuid.toString())
|
||||||
|
.requestPath(null)
|
||||||
|
.responsePath(null)
|
||||||
|
.requestFiles(new ArrayList<>())
|
||||||
|
.responseFiles(new ArrayList<>())
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
// response_path: response_dir + model_uuid
|
// request_path: tb_model_master.request_path 컬럼 값 사용
|
||||||
|
// request_path 컬럼에는 'AE366F3076504FACBF12106986202AB5' 형태의 값이 저장되어 있음
|
||||||
|
String requestPathFromDb = model.getRequestPath();
|
||||||
|
String requestPath;
|
||||||
|
if (requestPathFromDb != null && !requestPathFromDb.isEmpty()) {
|
||||||
|
// DB에 저장된 값이 있으면 symbolic_link_dir + request_path 조합
|
||||||
|
requestPath = symbolicLinkDir + "/" + requestPathFromDb;
|
||||||
|
} else {
|
||||||
|
// 없으면 기본값: symbolic_link_dir + model_uuid
|
||||||
|
requestPath = symbolicLinkDir + "/" + modelUuid;
|
||||||
|
}
|
||||||
|
|
||||||
|
// response_path: response_dir + model_uuid (UUID 사용)
|
||||||
String responsePath = responseDir + "/" + modelUuid;
|
String responsePath = responseDir + "/" + modelUuid;
|
||||||
|
|
||||||
// 파일 목록 조회
|
// 파일 목록 조회
|
||||||
@@ -290,10 +343,16 @@ public class FileManagerService {
|
|||||||
*/
|
*/
|
||||||
public FileManagerDto.DatasetFilePathRes getDatasetFilePath(UUID datasetUuid) {
|
public FileManagerDto.DatasetFilePathRes getDatasetFilePath(UUID datasetUuid) {
|
||||||
// tb_dataset 테이블에서 데이터셋 조회
|
// tb_dataset 테이블에서 데이터셋 조회
|
||||||
DatasetEntity dataset =
|
DatasetEntity dataset = datasetRepository.findByUuid(datasetUuid).orElse(null);
|
||||||
datasetRepository
|
|
||||||
.findByUuid(datasetUuid)
|
// 데이터셋이 존재하지 않으면 빈 데이터 반환
|
||||||
.orElseThrow(() -> new IllegalArgumentException("데이터셋을 찾을 수 없습니다: " + datasetUuid));
|
if (dataset == null) {
|
||||||
|
return FileManagerDto.DatasetFilePathRes.builder()
|
||||||
|
.datasetUuid(datasetUuid.toString())
|
||||||
|
.datasetPath(null)
|
||||||
|
.files(new ArrayList<>())
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
// dataset_path 컬럼이 있으면 사용, 없으면 request_dir + uuid 사용
|
// dataset_path 컬럼이 있으면 사용, 없으면 request_dir + uuid 사용
|
||||||
String datasetPath = dataset.getDatasetPath();
|
String datasetPath = dataset.getDatasetPath();
|
||||||
@@ -318,15 +377,41 @@ public class FileManagerService {
|
|||||||
* @return 디렉토리 용량 정보
|
* @return 디렉토리 용량 정보
|
||||||
*/
|
*/
|
||||||
public FileManagerDto.DirectoryCapacityRes checkDirectoryCapacity(String directoryPath) {
|
public FileManagerDto.DirectoryCapacityRes checkDirectoryCapacity(String directoryPath) {
|
||||||
validatePath(directoryPath);
|
// 경로 검증은 수행하되, 예외를 throw하지 않고 빈 데이터 반환
|
||||||
|
try {
|
||||||
|
validatePath(directoryPath);
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
log.debug("유효하지 않은 경로: {}", directoryPath);
|
||||||
|
return FileManagerDto.DirectoryCapacityRes.builder()
|
||||||
|
.directoryPath(directoryPath)
|
||||||
|
.fileCount(0)
|
||||||
|
.directoryCount(0)
|
||||||
|
.totalSize(0L)
|
||||||
|
.totalSizeFormatted("0 B")
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
Path directory = Paths.get(directoryPath);
|
Path directory = Paths.get(directoryPath);
|
||||||
if (!Files.exists(directory)) {
|
if (!Files.exists(directory)) {
|
||||||
throw new IllegalArgumentException("디렉토리가 존재하지 않습니다: " + directoryPath);
|
log.debug("디렉토리가 존재하지 않습니다: {}", directoryPath);
|
||||||
|
return FileManagerDto.DirectoryCapacityRes.builder()
|
||||||
|
.directoryPath(directoryPath)
|
||||||
|
.fileCount(0)
|
||||||
|
.directoryCount(0)
|
||||||
|
.totalSize(0L)
|
||||||
|
.totalSizeFormatted("0 B")
|
||||||
|
.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!Files.isDirectory(directory)) {
|
if (!Files.isDirectory(directory)) {
|
||||||
throw new IllegalArgumentException("디렉토리 경로가 아닙니다: " + directoryPath);
|
log.debug("디렉토리 경로가 아닙니다: {}", directoryPath);
|
||||||
|
return FileManagerDto.DirectoryCapacityRes.builder()
|
||||||
|
.directoryPath(directoryPath)
|
||||||
|
.fileCount(0)
|
||||||
|
.directoryCount(0)
|
||||||
|
.totalSize(0L)
|
||||||
|
.totalSizeFormatted("0 B")
|
||||||
|
.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
final long[] totalSize = {0};
|
final long[] totalSize = {0};
|
||||||
@@ -353,8 +438,14 @@ public class FileManagerService {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
log.error("디렉토리 용량 체크 중 오류 발생: {}", directoryPath, e);
|
log.debug("디렉토리 용량 체크 중 오류 발생: {}", directoryPath, e);
|
||||||
throw new RuntimeException("디렉토리 용량 체크에 실패했습니다: " + e.getMessage());
|
return FileManagerDto.DirectoryCapacityRes.builder()
|
||||||
|
.directoryPath(directoryPath)
|
||||||
|
.fileCount(0)
|
||||||
|
.directoryCount(0)
|
||||||
|
.totalSize(0L)
|
||||||
|
.totalSizeFormatted("0 B")
|
||||||
|
.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
return FileManagerDto.DirectoryCapacityRes.builder()
|
return FileManagerDto.DirectoryCapacityRes.builder()
|
||||||
@@ -444,19 +535,19 @@ public class FileManagerService {
|
|||||||
|
|
||||||
Path directory = Paths.get(directoryPath);
|
Path directory = Paths.get(directoryPath);
|
||||||
if (!Files.exists(directory)) {
|
if (!Files.exists(directory)) {
|
||||||
log.warn("디렉토리가 존재하지 않습니다: {}", directoryPath);
|
log.debug("디렉토리가 존재하지 않습니다: {}", directoryPath);
|
||||||
return files;
|
return files;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!Files.isDirectory(directory)) {
|
if (!Files.isDirectory(directory)) {
|
||||||
log.warn("디렉토리 경로가 아닙니다: {}", directoryPath);
|
log.debug("디렉토리 경로가 아닙니다: {}", directoryPath);
|
||||||
return files;
|
return files;
|
||||||
}
|
}
|
||||||
|
|
||||||
try (Stream<Path> stream = Files.list(directory)) {
|
try (Stream<Path> stream = Files.list(directory)) {
|
||||||
stream.forEach(path -> files.add(createFileInfo(path)));
|
stream.forEach(path -> files.add(createFileInfo(path)));
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
log.error("파일 목록 조회 중 오류 발생: {}", directoryPath, e);
|
log.debug("파일 목록 조회 중 오류 발생: {}", directoryPath, e);
|
||||||
}
|
}
|
||||||
|
|
||||||
return files;
|
return files;
|
||||||
@@ -474,4 +565,130 @@ public class FileManagerService {
|
|||||||
return String.format("%.2f GB", size / (1024.0 * 1024.0 * 1024.0));
|
return String.format("%.2f GB", size / (1024.0 * 1024.0 * 1024.0));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 저장공간 정보 조회 (남은 공간 포함) 고정 경로: /home/kcomu/data
|
||||||
|
*
|
||||||
|
* @return 저장공간 정보 (사용량, 남은 공간, 디스크 용량)
|
||||||
|
*/
|
||||||
|
public FileManagerDto.StorageSpaceRes getStorageSpaceInfo() {
|
||||||
|
// 고정 경로: /home/kcomu/data
|
||||||
|
String directoryPath = "/home/kcomu/data";
|
||||||
|
|
||||||
|
Path directory = Paths.get(directoryPath);
|
||||||
|
if (!Files.exists(directory)) {
|
||||||
|
log.debug("디렉토리가 존재하지 않습니다: {}", directoryPath);
|
||||||
|
return FileManagerDto.StorageSpaceRes.builder()
|
||||||
|
.directoryPath(directoryPath)
|
||||||
|
.fileCount(0)
|
||||||
|
.directoryCount(0)
|
||||||
|
.usedSize(0L)
|
||||||
|
.usedSizeFormatted("0 B")
|
||||||
|
.totalDiskSpace(0L)
|
||||||
|
.totalDiskSpaceFormatted("0 B")
|
||||||
|
.freeSpace(0L)
|
||||||
|
.freeSpaceFormatted("0 B")
|
||||||
|
.usableSpace(0L)
|
||||||
|
.usableSpaceFormatted("0 B")
|
||||||
|
.usagePercentage(0.0)
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!Files.isDirectory(directory)) {
|
||||||
|
log.debug("디렉토리 경로가 아닙니다: {}", directoryPath);
|
||||||
|
return FileManagerDto.StorageSpaceRes.builder()
|
||||||
|
.directoryPath(directoryPath)
|
||||||
|
.fileCount(0)
|
||||||
|
.directoryCount(0)
|
||||||
|
.usedSize(0L)
|
||||||
|
.usedSizeFormatted("0 B")
|
||||||
|
.totalDiskSpace(0L)
|
||||||
|
.totalDiskSpaceFormatted("0 B")
|
||||||
|
.freeSpace(0L)
|
||||||
|
.freeSpaceFormatted("0 B")
|
||||||
|
.usableSpace(0L)
|
||||||
|
.usableSpaceFormatted("0 B")
|
||||||
|
.usagePercentage(0.0)
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 디렉토리 사용량 계산 (재귀적으로 모든 파일 크기 합산)
|
||||||
|
final long[] usedSize = {0};
|
||||||
|
final int[] fileCount = {0};
|
||||||
|
final int[] directoryCount = {0};
|
||||||
|
|
||||||
|
try {
|
||||||
|
Files.walkFileTree(
|
||||||
|
directory,
|
||||||
|
new SimpleFileVisitor<>() {
|
||||||
|
@Override
|
||||||
|
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) {
|
||||||
|
usedSize[0] += attrs.size();
|
||||||
|
fileCount[0]++;
|
||||||
|
return FileVisitResult.CONTINUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) {
|
||||||
|
if (!dir.equals(directory)) {
|
||||||
|
directoryCount[0]++;
|
||||||
|
}
|
||||||
|
return FileVisitResult.CONTINUE;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} catch (IOException e) {
|
||||||
|
log.debug("디렉토리 용량 계산 중 오류 발생: {}", directoryPath, e);
|
||||||
|
return FileManagerDto.StorageSpaceRes.builder()
|
||||||
|
.directoryPath(directoryPath)
|
||||||
|
.fileCount(0)
|
||||||
|
.directoryCount(0)
|
||||||
|
.usedSize(0L)
|
||||||
|
.usedSizeFormatted("0 B")
|
||||||
|
.totalDiskSpace(0L)
|
||||||
|
.totalDiskSpaceFormatted("0 B")
|
||||||
|
.freeSpace(0L)
|
||||||
|
.freeSpaceFormatted("0 B")
|
||||||
|
.usableSpace(0L)
|
||||||
|
.usableSpaceFormatted("0 B")
|
||||||
|
.usagePercentage(0.0)
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 디스크 공간 정보 조회 (FileStore 사용)
|
||||||
|
long totalDiskSpace = 0;
|
||||||
|
long freeSpace = 0;
|
||||||
|
long usableSpace = 0;
|
||||||
|
double usagePercentage = 0.0;
|
||||||
|
|
||||||
|
try {
|
||||||
|
java.nio.file.FileStore fileStore = Files.getFileStore(directory);
|
||||||
|
totalDiskSpace = fileStore.getTotalSpace(); // 전체 디스크 용량
|
||||||
|
freeSpace = fileStore.getUnallocatedSpace(); // 남은 저장공간 (할당되지 않은 공간)
|
||||||
|
usableSpace = fileStore.getUsableSpace(); // 사용 가능한 공간 (실제 사용 가능)
|
||||||
|
|
||||||
|
// 디스크 사용률 계산
|
||||||
|
if (totalDiskSpace > 0) {
|
||||||
|
long usedDiskSpace = totalDiskSpace - freeSpace;
|
||||||
|
usagePercentage = (usedDiskSpace * 100.0) / totalDiskSpace;
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
log.debug("디스크 공간 정보 조회 중 오류 발생: {}", directoryPath, e);
|
||||||
|
// 디스크 정보 조회 실패 시에도 디렉토리 용량은 반환
|
||||||
|
}
|
||||||
|
|
||||||
|
return FileManagerDto.StorageSpaceRes.builder()
|
||||||
|
.directoryPath(directoryPath)
|
||||||
|
.fileCount(fileCount[0])
|
||||||
|
.directoryCount(directoryCount[0])
|
||||||
|
.usedSize(usedSize[0])
|
||||||
|
.usedSizeFormatted(formatFileSize(usedSize[0]))
|
||||||
|
.totalDiskSpace(totalDiskSpace)
|
||||||
|
.totalDiskSpaceFormatted(formatFileSize(totalDiskSpace))
|
||||||
|
.freeSpace(freeSpace)
|
||||||
|
.freeSpaceFormatted(formatFileSize(freeSpace))
|
||||||
|
.usableSpace(usableSpace)
|
||||||
|
.usableSpaceFormatted(formatFileSize(usableSpace))
|
||||||
|
.usagePercentage(Math.round(usagePercentage * 100.0) / 100.0)
|
||||||
|
.build();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -142,6 +142,9 @@ public class ModelTrainDetailDto {
|
|||||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||||
private Long landCoverCnt;
|
private Long landCoverCnt;
|
||||||
|
|
||||||
|
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||||
|
private Long solarPanelCnt;
|
||||||
|
|
||||||
public MappingDataset(
|
public MappingDataset(
|
||||||
Long modelId,
|
Long modelId,
|
||||||
Long datasetId,
|
Long datasetId,
|
||||||
@@ -152,17 +155,20 @@ public class ModelTrainDetailDto {
|
|||||||
Long buildingCnt,
|
Long buildingCnt,
|
||||||
Long containerCnt,
|
Long containerCnt,
|
||||||
Long wasteCnt,
|
Long wasteCnt,
|
||||||
Long landCoverCnt) {
|
Long landCoverCnt,
|
||||||
|
Long solarPanelCnt) {
|
||||||
this.modelId = modelId;
|
this.modelId = modelId;
|
||||||
this.datasetId = datasetId;
|
this.datasetId = datasetId;
|
||||||
this.dataType = dataType;
|
this.dataType = dataType;
|
||||||
this.compareYyyy = compareYyyy;
|
this.compareYyyy = compareYyyy;
|
||||||
this.targetYyyy = targetYyyy;
|
this.targetYyyy = targetYyyy;
|
||||||
this.roundNo = roundNo;
|
this.roundNo = roundNo;
|
||||||
this.buildingCnt = buildingCnt;
|
this.buildingCnt = toNullIfZero(buildingCnt);
|
||||||
this.containerCnt = containerCnt;
|
this.containerCnt = toNullIfZero(containerCnt);
|
||||||
this.wasteCnt = wasteCnt;
|
this.wasteCnt = toNullIfZero(wasteCnt);
|
||||||
this.landCoverCnt = landCoverCnt;
|
this.landCoverCnt = toNullIfZero(landCoverCnt);
|
||||||
|
this.solarPanelCnt = toNullIfZero(solarPanelCnt);
|
||||||
|
|
||||||
this.dataTypeName = getDataTypeName(this.dataType);
|
this.dataTypeName = getDataTypeName(this.dataType);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -172,6 +178,10 @@ public class ModelTrainDetailDto {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static Long toNullIfZero(Long value) {
|
||||||
|
return (value == null || value == 0L) ? null : value;
|
||||||
|
}
|
||||||
|
|
||||||
@Getter
|
@Getter
|
||||||
@Setter
|
@Setter
|
||||||
@NoArgsConstructor
|
@NoArgsConstructor
|
||||||
|
|||||||
@@ -201,7 +201,7 @@ public class ModelTrainMngDto {
|
|||||||
private Long LandCoverCnt;
|
private Long LandCoverCnt;
|
||||||
|
|
||||||
@Schema(description = "태양광", example = "0")
|
@Schema(description = "태양광", example = "0")
|
||||||
private Long solarCnt;
|
private Long solarPanelCnt;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Getter
|
@Getter
|
||||||
|
|||||||
@@ -140,6 +140,7 @@ public class ModelTrainMngCoreService {
|
|||||||
* @param addReq 요청 파라미터
|
* @param addReq 요청 파라미터
|
||||||
*/
|
*/
|
||||||
public void saveModelDataset(Long modelId, ModelTrainMngDto.AddReq addReq) {
|
public void saveModelDataset(Long modelId, ModelTrainMngDto.AddReq addReq) {
|
||||||
|
|
||||||
TrainingDataset dataset = addReq.getTrainingDataset();
|
TrainingDataset dataset = addReq.getTrainingDataset();
|
||||||
ModelMasterEntity modelMasterEntity = new ModelMasterEntity();
|
ModelMasterEntity modelMasterEntity = new ModelMasterEntity();
|
||||||
ModelDatasetEntity datasetEntity = new ModelDatasetEntity();
|
ModelDatasetEntity datasetEntity = new ModelDatasetEntity();
|
||||||
@@ -155,7 +156,7 @@ public class ModelTrainMngCoreService {
|
|||||||
} else if (addReq.getModelNo().equals(ModelType.G3.getId())) {
|
} else if (addReq.getModelNo().equals(ModelType.G3.getId())) {
|
||||||
datasetEntity.setLandCoverCnt(dataset.getSummary().getLandCoverCnt());
|
datasetEntity.setLandCoverCnt(dataset.getSummary().getLandCoverCnt());
|
||||||
} else if (addReq.getModelNo().equals(ModelType.G4.getId())) {
|
} else if (addReq.getModelNo().equals(ModelType.G4.getId())) {
|
||||||
datasetEntity.setSolarCnt(dataset.getSummary().getSolarCnt());
|
datasetEntity.setSolarCnt(dataset.getSummary().getSolarPanelCnt());
|
||||||
}
|
}
|
||||||
|
|
||||||
datasetEntity.setCreatedUid(userUtil.getId());
|
datasetEntity.setCreatedUid(userUtil.getId());
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package com.kamco.cd.training.postgres.repository.model;
|
package com.kamco.cd.training.postgres.repository.model;
|
||||||
|
|
||||||
import static com.kamco.cd.training.postgres.entity.QDatasetEntity.datasetEntity;
|
import static com.kamco.cd.training.postgres.entity.QDatasetEntity.datasetEntity;
|
||||||
|
import static com.kamco.cd.training.postgres.entity.QDatasetObjEntity.datasetObjEntity;
|
||||||
import static com.kamco.cd.training.postgres.entity.QModelDatasetEntity.modelDatasetEntity;
|
import static com.kamco.cd.training.postgres.entity.QModelDatasetEntity.modelDatasetEntity;
|
||||||
import static com.kamco.cd.training.postgres.entity.QModelDatasetMappEntity.modelDatasetMappEntity;
|
import static com.kamco.cd.training.postgres.entity.QModelDatasetMappEntity.modelDatasetMappEntity;
|
||||||
import static com.kamco.cd.training.postgres.entity.QModelHyperParamEntity.modelHyperParamEntity;
|
import static com.kamco.cd.training.postgres.entity.QModelHyperParamEntity.modelHyperParamEntity;
|
||||||
@@ -9,6 +10,8 @@ import static com.kamco.cd.training.postgres.entity.QModelMetricsTestEntity.mode
|
|||||||
import static com.kamco.cd.training.postgres.entity.QModelMetricsTrainEntity.modelMetricsTrainEntity;
|
import static com.kamco.cd.training.postgres.entity.QModelMetricsTrainEntity.modelMetricsTrainEntity;
|
||||||
import static com.kamco.cd.training.postgres.entity.QModelMetricsValidationEntity.modelMetricsValidationEntity;
|
import static com.kamco.cd.training.postgres.entity.QModelMetricsValidationEntity.modelMetricsValidationEntity;
|
||||||
|
|
||||||
|
import com.kamco.cd.training.common.enums.DetectionClassification;
|
||||||
|
import com.kamco.cd.training.common.enums.ModelType;
|
||||||
import com.kamco.cd.training.common.enums.TrainStatusType;
|
import com.kamco.cd.training.common.enums.TrainStatusType;
|
||||||
import com.kamco.cd.training.model.dto.ModelTrainDetailDto.DetailSummary;
|
import com.kamco.cd.training.model.dto.ModelTrainDetailDto.DetailSummary;
|
||||||
import com.kamco.cd.training.model.dto.ModelTrainDetailDto.HyperSummary;
|
import com.kamco.cd.training.model.dto.ModelTrainDetailDto.HyperSummary;
|
||||||
@@ -25,6 +28,7 @@ import com.kamco.cd.training.postgres.entity.QModelHyperParamEntity;
|
|||||||
import com.kamco.cd.training.postgres.entity.QModelMasterEntity;
|
import com.kamco.cd.training.postgres.entity.QModelMasterEntity;
|
||||||
import com.querydsl.core.types.Expression;
|
import com.querydsl.core.types.Expression;
|
||||||
import com.querydsl.core.types.Projections;
|
import com.querydsl.core.types.Projections;
|
||||||
|
import com.querydsl.core.types.dsl.CaseBuilder;
|
||||||
import com.querydsl.jpa.JPAExpressions;
|
import com.querydsl.jpa.JPAExpressions;
|
||||||
import com.querydsl.jpa.impl.JPAQueryFactory;
|
import com.querydsl.jpa.impl.JPAQueryFactory;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
@@ -154,10 +158,78 @@ public class ModelDetailRepositoryImpl implements ModelDetailRepositoryCustom {
|
|||||||
datasetEntity.compareYyyy,
|
datasetEntity.compareYyyy,
|
||||||
datasetEntity.targetYyyy,
|
datasetEntity.targetYyyy,
|
||||||
datasetEntity.roundNo,
|
datasetEntity.roundNo,
|
||||||
modelDatasetEntity.buildingCnt,
|
|
||||||
modelDatasetEntity.containerCnt,
|
// G1 - building
|
||||||
modelDatasetEntity.wasteCnt,
|
new CaseBuilder()
|
||||||
modelDatasetEntity.landCoverCnt))
|
.when(
|
||||||
|
modelMasterEntity
|
||||||
|
.modelNo
|
||||||
|
.eq(ModelType.G1.getId())
|
||||||
|
.and(
|
||||||
|
datasetObjEntity.targetClassCd.eq(
|
||||||
|
DetectionClassification.BUILDING.getId())))
|
||||||
|
.then(1L)
|
||||||
|
.otherwise(0L)
|
||||||
|
.sum(),
|
||||||
|
|
||||||
|
// G1 - container
|
||||||
|
new CaseBuilder()
|
||||||
|
.when(
|
||||||
|
modelMasterEntity
|
||||||
|
.modelNo
|
||||||
|
.eq(ModelType.G1.getId())
|
||||||
|
.and(
|
||||||
|
datasetObjEntity.targetClassCd.eq(
|
||||||
|
DetectionClassification.CONTAINER.getId())))
|
||||||
|
.then(1L)
|
||||||
|
.otherwise(0L)
|
||||||
|
.sum(),
|
||||||
|
|
||||||
|
// G2 - waste
|
||||||
|
new CaseBuilder()
|
||||||
|
.when(
|
||||||
|
modelMasterEntity
|
||||||
|
.modelNo
|
||||||
|
.eq(ModelType.G2.getId())
|
||||||
|
.and(
|
||||||
|
datasetObjEntity.targetClassCd.eq(
|
||||||
|
DetectionClassification.WASTE.getId())))
|
||||||
|
.then(1L)
|
||||||
|
.otherwise(0L)
|
||||||
|
.sum(),
|
||||||
|
|
||||||
|
// G3 - 나머지
|
||||||
|
new CaseBuilder()
|
||||||
|
.when(
|
||||||
|
modelMasterEntity
|
||||||
|
.modelNo
|
||||||
|
.eq(ModelType.G3.getId())
|
||||||
|
.and(
|
||||||
|
datasetObjEntity
|
||||||
|
.targetClassCd
|
||||||
|
.isNotNull()
|
||||||
|
.and(
|
||||||
|
datasetObjEntity.targetClassCd.notIn(
|
||||||
|
DetectionClassification.BUILDING.getId(),
|
||||||
|
DetectionClassification.CONTAINER.getId(),
|
||||||
|
DetectionClassification.WASTE.getId(),
|
||||||
|
DetectionClassification.SOLAR.getId()))))
|
||||||
|
.then(1L)
|
||||||
|
.otherwise(0L)
|
||||||
|
.sum(),
|
||||||
|
|
||||||
|
// G4 - solar
|
||||||
|
new CaseBuilder()
|
||||||
|
.when(
|
||||||
|
modelMasterEntity
|
||||||
|
.modelNo
|
||||||
|
.eq(ModelType.G4.getId())
|
||||||
|
.and(
|
||||||
|
datasetObjEntity.targetClassCd.eq(
|
||||||
|
DetectionClassification.SOLAR.getId())))
|
||||||
|
.then(1L)
|
||||||
|
.otherwise(0L)
|
||||||
|
.sum()))
|
||||||
.from(modelMasterEntity)
|
.from(modelMasterEntity)
|
||||||
.innerJoin(modelDatasetEntity)
|
.innerJoin(modelDatasetEntity)
|
||||||
.on(modelMasterEntity.id.eq(modelDatasetEntity.model.id))
|
.on(modelMasterEntity.id.eq(modelDatasetEntity.model.id))
|
||||||
@@ -165,7 +237,16 @@ public class ModelDetailRepositoryImpl implements ModelDetailRepositoryCustom {
|
|||||||
.on(modelMasterEntity.id.eq(modelDatasetMappEntity.modelUid))
|
.on(modelMasterEntity.id.eq(modelDatasetMappEntity.modelUid))
|
||||||
.innerJoin(datasetEntity)
|
.innerJoin(datasetEntity)
|
||||||
.on(modelDatasetMappEntity.datasetUid.eq(datasetEntity.id))
|
.on(modelDatasetMappEntity.datasetUid.eq(datasetEntity.id))
|
||||||
|
.leftJoin(datasetObjEntity)
|
||||||
|
.on(datasetEntity.id.eq(datasetObjEntity.datasetUid))
|
||||||
.where(modelMasterEntity.uuid.eq(uuid))
|
.where(modelMasterEntity.uuid.eq(uuid))
|
||||||
|
.groupBy(
|
||||||
|
modelMasterEntity.id,
|
||||||
|
datasetEntity.id,
|
||||||
|
datasetEntity.dataType,
|
||||||
|
datasetEntity.compareYyyy,
|
||||||
|
datasetEntity.targetYyyy,
|
||||||
|
datasetEntity.roundNo)
|
||||||
.fetch();
|
.fetch();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user