2009-08-24 3 views
1

«Лучшая практика» (как я вижу) для атомарного создания нового файла - открыть временный файл (используя tmpfile()), а затем переместить файл в его окончательное местоположение.Лучший способ для атомарного создания файлов

Однако это не сработает, если временный файл находится на другой точке монтирования, так как это приведет к постепенному наращиванию файла и дополнительно приведет к ненужным накладным расходам ввода-вывода.

Другой вариант - создать временный файл в том же каталоге, что и конечный пункт назначения, но это имеет недостаток в создании необычного файла для пользователя (такие приложения, как MS Word и ViM, делают это, но я также рассматриваю это плохое поведение).

Есть ли аналогичный метод, как tmpfile(), который позволит мне указать точку монтирования? Я понимаю, что это, вероятно, не существует встроенной в PHP, поэтому приемлема Posix/C-функция или вызов оболочки.

ответ

1

Протокол maildir, разработанный для qmail, обеспечивает безопасное создание файлов для нескольких авторов в один и тот же целевой каталог, даже через NFS. В этой схеме каталог «tempfile» гарантированно находится в той же файловой системе, что и целевой каталог.

Алгоритм удобно реализован в эффективной утилиты оболочки, safecat, чья страница руководства представлен алгоритм, как:

safecat применяет алгоритм MAILDIR путем записи данных в шесть этапов. Во-первых, это stat() s из двух каталогов tempdir и destdir и выходит из , если оба каталога не существуют и могут быть доступны для записи. Во-вторых, это stat() s имя tempdir/time.pid.host, где время - это число секунд с в начале 1970 года по Гринвичу, pid - это идентификатор процесса программы, а host - имя хоста. В-третьих, если stat() вернул что-либо, кроме ENOENT, , программа засыпает на две секунды, обновляет время и снова старается stat() , ограниченное количество раз. В-четвертых, программа создает tempdir/time.pid.host. В-пятых, программа NFS - записывает сообщение в файл . В-шестых, ссылка программы() s на файл destdir/time.pid.host. На этапе , чтобы данные были успешно записаны.

Кроме того, safecat запускает 24-часовой таймер перед созданием tempdir/time.pid.host и прерывает запись, если таймер истекает. По ошибке ошибка, время ожидания или нормальное завершение, safecat пытается отменить связь() tempdir/time.pid.host.

0

Как вы говорите о «точке монтирования», я предполагаю, что вы находитесь в среде, подобной unix.

Возможно, вы можете считать это обходным путем или неправильным поведением, но я думаю, что создание скрытого файла (.tmpfile) temp в той же папке назначения может быть приемлемым.

Вы можете, конечно, создать определенную папку в той же точке монтирования, которая недоступна для приложения, подходящего для этой задачи, и таким образом имитировать tempfile() на той же точке монтирования, если вы не хотите видеть какой-либо ложный файл в директории назначения.

+0

В Windows есть точки монтирования, по крайней мере, на NTFS. – Thorarin

+0

Это на самом деле мой второй вариант, которого я бы хотел избежать. – Evert

+0

@Thorarin, можете ли вы узнать больше об этом. Благодарю. – drAlberT

2

Нет, такой метод не существует в стеке POSIX. tmpfile() и tmpname() использовать для нормального темпа. Существует tempnam(), где вы можете указать целевой каталог для временного файла. Но это в основном способ реализовать второй вариант, который вы описали.

+0

Мне было любопытно, есть ли способ открыть INode и предоставить только имя файла по дороге. Я знаю, что можно открывать файлы, отключать файлы, а затем продолжать писать. – Evert

+0

Я не думаю, что это возможно, но было бы хорошо знать точно. Если я помню, я посмотрю исходный код VFS. – dmeister

-1

Мне нужно было сделать что-то подобное и отправился с MySQL DB. Просто сохранил информацию, которая мне нужна в таблице, и когда я закончил, я просто удалил запись. Просто мысль :)

+0

Это может привести к аналогичному объему накладных расходов ввода-вывода. Часто база данных даже не на том же сервере. – Thorarin

+0

Использование MySQL, безусловно, хуже – Evert