2009-08-24 4 views
1

원자재로 새로운 파일을 만드는 '최상의 방법'은 (tmpfile()을 사용하여) 임시 파일을 연 다음 파일을 최종 위치로 이동하는 것입니다.원자 적으로 파일을 만드는 가장 좋은 방법

그러나 임시 파일이 다른 마운트 지점에 있으면이 기능이 제대로 작동하지 않습니다. 파일이 점차 많아지고 불필요한 IO 오버 헤드가 발생하게됩니다.

또 다른 옵션은 최종 목적지와 동일한 디렉토리에 임시 파일을 만드는 것이지만 사용자에게 비정상적인 파일을 생성하는 단점이 있습니다 (MS Word 및 ViM과 같은 Apps에서이 작업을 수행하지만이 또한 고려해야합니다). 나쁜 행동).

마운트 지점을 지정할 수있는 tmpfile()과 비슷한 방법이 있습니까? PHP에 내장되어 있지 않기 때문에 POSIX/C 함수 나 쉘 호출도 가능하다는 것을 알고 있습니다.

답변

1

qmail 용으로 개발 된 프로토콜은 NFS를 통해도 동일한 대상 디렉토리에 여러 작성자를위한 안전한 파일 작성을 제공합니다. 이 체계에서 "tempfile"디렉토리는 대상 디렉토리와 동일한 파일 시스템에 있어야합니다.

safecat 여섯 단계에서 데이터를 작성하여 MAILDIR 알고리즘을 적용

알고리즘

편리 그 맨 같은 알고리즘을 제공하는 효율적인 쉘 유틸리티 safecat로 구현된다. 먼저 두 개의 디렉토리 tempdir 및 destdir을 stat()하고 두 디렉토리가 존재하고 쓰기 가능하지 않으면 을 종료합니다. 둘째로, 이라는 이름의 tempdir/time.pid.host (여기서 time은 1970 년 GMT 시작, pid는 프로그램의 프로세스 ID, 호스트는 호스트 이름 )의 초 수입니다. 셋째, stat()가 ENOENT 이외의 값을 반환하면 프로그램은 2 초 동안 대기하고 시간을 업데이트하며 다시 제한된 횟수만큼 stat() 을 다시 시도합니다. 넷째, 프로그램에서 tempdir/time.pid.host를 만듭니다. 다섯째, 프로그램 NFS는 메시지를 파일에 기록합니다. 여섯 번째, 프로그램은 파일을 destdir/time.pid.host에 link()합니다. 에 데이터가 성공적으로 기록됩니다.

또한 safecat은 tempdir/time.pid.host를 생성하기 전에 24 시간 타이머를 시작하고 타이머가 만료되면 쓰기를 중단합니다. 오류, 시간 초과 또는 정상 완료시 safecat에서 tempdir/time.pid.host 링크를 해제하려고 시도합니다.

0

"마운트 포인트"에 대해 이야기하면서 나는 유닉스 환경에 있다고 가정합니다.

어쩌면 해결 방법이나 불량 행동으로 생각할 수도 있지만 같은 대상 폴더에 숨김 (.tmpfile) 임시 파일을 만들면 문제가되지 않을 수도 있습니다.

물론이 작업에 적합한 응용 프로그램에서 액세스 할 수없는 동일한 탑재 지점에 특정 폴더를 만들 수 있습니다.이 방법은 위조 파일을보고 싶지 않은 경우 동일한 탑재 지점에서 tempfile()을 시뮬레이트합니다. 목적지에서.

+0

Windows에는 적어도 NTFS에서 탑재 지점이 있습니다. – Thorarin

+0

이것은 실제로 제 두 번째 옵션입니다. 나는 피하고 싶습니다. – Evert

+0

@ Thorarin,이 문제에 대한 정보를 좀 더 많이 주시겠습니까? 감사. – drAlberT

2

아니요, 그런 방법은 POSIX 스택에 없습니다. tmpfile() 및 tmpname() 정상적인 temp 디렉토리를 사용합니다. tempnam()이 있는데 여기에서 임시 파일의 대상 디렉토리를 지정할 수 있습니다. 하지만 기본적으로 설명하는 두 번째 옵션을 구현하는 방법입니다.

+0

아마도 INode를 열고 도로 아래에 파일 이름 만 제공하는 방법이 있다면 궁금합니다. 파일을 열고, 파일의 링크를 끊고, 계속 쓰는 것이 가능하다는 것을 알고 있습니다. – Evert

+0

나는 이것이 가능하다고 생각하지 않지만, 정확하게 알면 좋을 것이다. 기억한다면 VFS 소스 코드를 살펴볼 것입니다. – dmeister

-1

나는 이와 같이해야만했으며 MySQL DB와 함께 갔다. 그냥 테이블에 필요한 정보를 저장하고 완료되면 레코드를 삭제했습니다. 그냥 생각 :

+0

그러나 이와 비슷한 양의 I/O 오버 헤드가 발생할 수 있습니다. 흔히 데이터베이스는 동일한 서버에 있지 않습니다. – Thorarin

+0

MySQL을 사용하는 것은 분명 더 나쁩니다. – Evert

관련 문제