나는 데이터 전달을 보장하는 솔루션을 운영한다. 파일을 주고받는 단순한 요건을 처리하는데 에러가 발생했다. Target Directory에 파일이 저장되지 않는다.
"어? 왜이러지?"
먼저, 문제를 분석하기 위해 환경 구성을 확인한다. 정상적인 환경과 비정상적인 환경을 비교하여 차이점을 찾는다. 대부분 답은 다름에 있다.
환경 구성은 단순하다. Middleware를 통해 Endpoint는 File을 전달 받는다. 특이한 점이 있다면 2개의 다른 파일 시스템을 쓴다는 것!
- Middleware로 부터 파일 조각을 전달 받는다.
- 파일 조각을
/home/usr/temp
경로에 순차적으로write
한다./home/usr/temp
에 파일이 전체가write
되면/app/dist
로 파일을 옮긴다.※
/home/usr/temp
는/app/dist
서로 다른 파일 시스템이다.
로그를 보니 아래의 코드에서 문제가 발생했다. 임시 경로인 /home/usr/temp
에는 정상적으로 파일이 존하는데, Target Dirctory인 /app/dist
는 파일이 존재하지 않는다. rename
함수를 통해 로 옮기는 부분에서 0
이 아니라 -1
이 리턴하면서, 파일이 정상적으로 수신되지 않은 것 처럼 보이는 것이다.
if(0 != rename(frompath, targetpath)) {
sprintf("Error write target file")
}
rename
함수는 <stdlib.h>
C언어의 표준 라이브러리에서 제공하는 함수인데 왜 안되지? rename
함수에는 문제가 있을리 없다. 단지, 내가 모르는 부분이 있을 뿐!
rename
함수의 실제 구현을 살펴보면 로직은 매우 단순한데 아래 두개의 Step 이 전부다.
__link
함수를 통해old
파일에new
라는 hard link 를 생성한다.__unlink
함수를 통해 기존hard link
old
를 제거한다.
rename
함수에서 hard link
가 주요한 역할을 함으로 주의 깊게 살펴보아야 할 것 같다.
int
rename (const char *old, const char *new)
{
int save = errno;
if (__link (old, new) < 0)
{
if (errno == EEXIST)
{
__set_errno (save);
/* Race condition, required for 1003.1 conformance. */
if (__unlink (new) < 0
|| __link (old, new) < 0)
return -1;
}
else
return -1;
}
if (__unlink (old) < 0)
{
save = errno;
if (__unlink (new) == 0)
__set_errno (save);
return -1;
}
return 0;
}
컴퓨팅 시스템에는 파일을 위한 2개의 링크가 존재한다. 하나는 Hard Link
이고 또 다른 하나는 Soft Link
이다. 나는 이 두개를 이렇게 이해하는데,
Hard Link
는 파일 이름으로 실제 데이터에 접근할 수 있도록 하는 것Soft Link
는 바로가기. 원본 파일의 이름 시스템(Hard Link
?)을 가르키도록 하는 것사실
Hard Link
는Inode
와 관련되어 있고,Inode
대한 건 여기서 확인 할 수 있다.
'Hard Link
는 파일 이름으로 실제 데이터에 접근할 수 있도록 한다.'라고 정의하면 왜 모든 파일이 적어도 하나의 Hard Link
가 존재해야 하는지 이해 수 있다. 바로, 파일 이름으로 실제 데이터(physical data)에 접근해야 하기 때문이다.
아래의 그림은 Hard Link
의 동작 방법을 표현한 그림이다. 디렉터리 dirA, dirB, dirC의 파일 이름 name1, name2, name3은 Inode 12345
를 가르키고 있다. Inode 12345
에는 파일에 대한 내용과 그리고 Hard Link
의 갯수에 대한 정보를 가지고 있다.
여기서 dirD에 파일 이름 name4로 Hard Link
를 추가하면, 추가된 Hard Link
는 Inode 12345
를 가르키고 Hard Link
수를 4로 변경한다. Inode
를 새로 생성하지 않는다.
반면에, Soft Link
를 생성하면 Inode
가 생성된다. 그리고 Inode
에 실제 파일 경로를 저장한다. 아래 그림은 Soft Link
의 동작 방법을 보여준다. dirA의 파일 이름 name1은 Inode 12345
를 가르키고 있다. 여기에 dirB의 name2 라는 Soft Link
를 생성하면 새로운 Inode 13579
가 생성된다. Inode 13579
는 실제 파일(physical data)의 /dirA/name 의 경로를 가르킨다.
dirA에 있는 name1 파일을 삭제하면, dirB에 있는 Soft Link
파일 name2는 존재하지 않는 파일 경로를 가리키 때문에 액세스할 때 오류가 발생한다.
Hard Link
에는 제약 사항이 존재한다.
Hard Link
는 디렉토리에 생성할 수 없다.Hard Link
는 같은 파일 시스템에서 사용가능하다. 그 대신 Soft Link
를 사용해야 한다. Hard Link
의 최대 개수는 232 이다.Hard Link
에 대해 공부하다 보니 문제 발생 원인이 명확하게 보인다.
Hard Link 제약사항과 System Configuration Diagram을 보면 내가 운영하는 솔루션이 Hard Link
의 제약사항을 위반 하고 있음을 알 수 있다.
Hard Link
는 같은 파일 시스템에서 사용가능하다.
/home/usr/temp
과 /app/dist
은 서로 다른 파일 시스템이기 때문에 문제가 발생하는 것이다.
문제의 해결법은 두가지 이다.
첫째,
rename
함수를 사용하지 않는 것
둘째, Target Directory 와 Temp Directory를 같은 파일 시스템으로 변경하는 것
팀원들과 협의 끝에 나는 두 번째 방법을 선택해 수정했다.
일을 하면 할 수록 운영체제와 컴퓨터 구조론과 같은 Computer Sicence이 지식이 필요함을 느낀다. 다 필요한 것들인데 대학에서 공부 할 때는 왜 이리 쓸모 없게 느껴졌을까?