2013-12-09 5 views
0

Итак, у меня есть файловый сервер Samba, на котором моему Java-приложению нужно написать некоторые файлы. Дело в том, что есть еще одно приложение php (если скрипт php даже считается приложением), который агрессивно вытаскивает один и тот же каталог для новых файлов.Заблокировать будущий файл

Иногда скрипт php вытаскивает файл до того, как приложение Java будет полностью записывать его на диск. Вот немного ASCII Art, чтобы помочь визуализировать то, что я в настоящее время (но не работает): доля

Samba

/foo (мой Java приложение падает файл здесь)

/bar (каталог, который вытаскивает php)

Что я сейчас делаю, когда файл соответствует некоторым критериям, он перемещается в /bar, а затем подбирается php для большей обработки. Я пробовал другое дело, поэтому у меня был файл, который нельзя записывать и не читать, перед тем как позвонить renameTo.

Я немного искал FileLock, но, похоже, он не может блокировать будущие файлы. Поэтому мне интересно, какие возможности у меня есть здесь? Что я мог бы использовать, чтобы заблокировать файл от того, чтобы быть поднятым до того, как он полностью написан, не касаясь php (потому что, ну, это php, и я действительно не имею права изменять его прямо сейчас).

Благодаря

Edit 1

У меня есть некоторое представление о том, что сценарий PHP действительно делает, если это может помочь в любом случае.

Он читает файл каталога в цикле (используя readdir без сна).

Как только он находит имя файла, отличное от "." и «..», он называет file_get_contents и где это терпит неудачу, потому что файл не полностью записаны на диск (или даже не существует, так как код Java может даже не успел написать его между readdir и file_get_contents.

Edit 2

Это приложение Java заменяет старый PHP скрипт. Когда они реализовали его, они же проблема, у меня прямо сейчас. они решили, написав новый файл в /bar/tmpfile_put_contents) и затем используйте rename, чтобы переместить его в бар (похоже, что переименование должно быть атомарным). И он работает нормально до сих пор. Я не могу и не буду верить t Java не может сделать что-то лучше, чем то, что php делает ...

+0

Есть/foo и/bar в одной файловой системе? – rob

+0

@rob Да, они есть. – ALOToverflow

ответ

0

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

Один из подходов, который вы можете сделать, это создать отдельный файл временного замка (например: /bar/file1.lock), а /bar/file1 не закончил копирование. Удалите файл блокировки сразу после завершения копирования файла.

Затем измените PHP-код, чтобы убедиться, что файл не заблокирован перед его чтением.

+0

У меня была такая же мысль, но, к сожалению, проблема заключается в том, что изменение PHP не является вариантом. – rob

0

Вы упомянули, что вы пытались FileLock, но имейте в виду отказ от ответственности в Javadoc для этого метода:

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

Вы также упомянули вы используете File.renameTo, который также имеет некоторые оговорки (упомянутые в Javadoc):

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

Вместо File.renameTo, попробуйте Files.move с опцией ATOMIC_MOVE. Вам придется поймать AtomicMoveNotSupportedException и, возможно, вернуться к альтернативному обходному пути в случае, если атомный ход невозможен.

Вы можете создать жесткую связь с Files.createLink(Paths.get('/foo/myFile'), 'Paths.get('/bar/myFile')) затем удалите исходную запись каталога (в данном примере, /foo/myFile.

В противном случае, простое решение, которое не требует изменений в PHP является использование команды оболочки или системный вызов для перемещения файла из/foo в/bar. Например, вы можете использовать ProcessBuilder для вызова mv или позвонить по телефону ln, чтобы создать символическую ссылку или жесткую ссылку в/бар. У вас может быть такая же проблема с mv, если/foo и/bar находятся на разных файловых системах.

Если у вас есть roo t на сервере, вы также можете попробовать выполнить принудительное блокирование файлов. Я нашел example в C, но вы могли бы вызвать программу C с Java или адаптировать пример к Java, используя JNA (или JNI, если вы хотите наказать себя).

+0

Параметр ATOMIC_MOVE не отличается. Файл все еще подбирается, прежде чем полностью записать на диск. Я получаю странные исключения с ProcessBuilder, говоря, что файл/путь не существует (ошибка = 2), однако вставка точной командной строки в консоли ... – ALOToverflow

+0

Когда вы говорите, что вставка командной строки в консоли работает, вы просто подразумеваете, что он выполняется, или что он также решает проблему с PHP-скриптом, собирающим неполный файл? Добавьте к этому вопросу свой код ProcessBuilder и стек стека. – rob

+0

Он выполняет и до сих пор, он также решил проблему с php. Я добавлю немного больше контекста по этому вопросу. – ALOToverflow

 Смежные вопросы

  • Нет связанных вопросов^_^