Атомарные операции записи в файл (кроссплатформенный) - PullRequest
26 голосов
/ 12 января 2010

Как мне создать атомарную операцию записи файла? Файл должен быть написан службой Java и прочитан скриптами Python.
Для записи, чтения намного больше, чем записи. Но запись происходит партиями и, как правило, долго. Размер файла составляет мегабайты.

Прямо сейчас мой подход:

  • Запись содержимого файла во временный файл в тот же каталог
  • Удалить старый файл
  • Переименование временного файла в старое имя файла.

Это правильный подход? Как можно избежать условий, когда старый файл удаляется, но новое имя файла еще не переименовано?

Предлагает ли эти языки программирования ( python и java ) конструкции для блокировки и предотвращения этой ситуации?

Ответы [ 7 ]

10 голосов
/ 12 января 2010

AFAIK №

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

РЕДАКТИРОВАТЬ - Я ошибаюсь, по крайней мере, для POSIX-совместимых систем. Системный вызов POSIX rename выполняет атомарную замену, если файл с целевым именем уже существует ..., как указано @janneb. Этого должно быть достаточно для атомарной операции ОП.

Однако факт остается фактом: * Java 1010 * явно не гарантированно является атомарным, поэтому он не обеспечивает кросс-платформенное решение проблемы OP.

РЕДАКТИРОВАТЬ 2 - В Java 7 вы можете использовать java.nio.file.Files.move(Path source, Path target, CopyOption... options) с copyOptions и ATOMIC_MOVE. Если это не поддерживается (ОС / файловая система), вы должны получить исключение.

5 голосов
/ 12 января 2010

По крайней мере на платформах POSIX, пропустите шаг 3 (удалить старый файл). В POSIX переименование в файловой системе гарантированно является атомарным, а переименование поверх существующего файла заменяет его атомарно.

3 голосов
/ 12 января 2010

Это классическая проблема производителя / потребителя. Вы должны быть в состоянии решить эту проблему с помощью переименования файлов, что является атомарным в системах POSIX.

2 голосов
/ 10 декабря 2010

В Linux, Solaris, Unix это легко. Просто используйте rename () из вашей программы или mv. Файлы должны находиться в одной файловой системе.

В Windows это возможно, если вы можете управлять обеими программами. LockFileEx. Для чтения откройте shared lock в файле блокировки. Для записи откройте exclusive lock в файле блокировки. Блокировка в Windows - это странно, поэтому я рекомендую использовать для этого отдельный файл блокировки .

1 голос
/ 12 января 2010

Сценарии python запрашивают разрешение у службы. Пока служба пишет, она блокирует файл. Если блокировка существует, служба отклонит запрос python.

1 голос
/ 12 января 2010

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

Другое решение может заключаться в том, чтобы вообще не создавать файлы. Может быть, вы могли бы заставить свой процесс Java слушать порт и обслуживать данные оттуда, а не из файла?

1 голос
/ 12 января 2010

Попробуйте Java FileLock API

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...