Я разрабатываю приложение, которое опрашивает папку на сетевом файловом сервере (cifs) на предмет новых файлов в запланированном задании cron каждую минуту.
Когда он видит новый файл, он временно копирует его в локальную файловую систему, а затем выполняет различные действия с файлом, а затем удаляет его из локальной и сетевой файловых систем.
У меня есть опасения по поводу возможности возникновения состояния гонки, когда мое приложение опрашивает сетевую папку, в то время как кто-то добавляет файл в сетевую папку. Файлы невероятно малы (1 КБ), поэтому очень редко нужно, чтобы файл копировался при опросе папки, но это могло произойти.
Мой вопрос, это законное беспокойство и если да, то как мне справиться с этим?
Вот как я решил свои проблемы.
Обратите внимание, что у меня была эта проблема в нескольких областях моего рабочего процесса. во-первых, мне приходилось следить за новыми файлами в каталоге с моим приложением и следить за тем, чтобы они заканчивали передачу и т. д. Во-вторых, мне приходилось загружать файлы в каталог, за которым следит другая часть программного обеспечения, а) у меня нет контроль, и б) очень архаичен и не делает никакой проверки сам по себе.
Чтобы решить первую проблему:
В моем запланированном задании я просканировал каталог на наличие всех файлов, затем сгенерировал хэш md5 для каждого файла и сохранил его в таблице в базе данных вместе с путем к файлу.
В следующий раз, когда мое запланированное задание будет выполнено (через 1 минуту), я извлекаю все строки из базы данных (путь к файлу и хэш), проверяю, существует ли файл, и затем снова генерирую хэш md5 из файла. Если файл существует и хэш-код совпадает, я выполняю обработку файла (и удаляю его из каталога). Если один из этих двух завершится неудачно, я просто перейду к следующему файлу в цикле.
После обработки всех файлов я обрезаю таблицу, в которой были проиндексированы файлы, а затем переиндексирую все файлы, снова сохраняя их в базе данных. Минуту спустя, и моя работа начинается снова, потребляя файлы из индекса.
Таким образом, я никогда не работаю с файлами, которые я не проиндексировал с предыдущего запуска задания. Я полагаю, можно с уверенностью предположить, что если хеш файла не изменился в течение 1 минуты, то передача файла завершена, и я могу использовать его.
Чтобы решить вторую проблему:
Чтобы гарантировать, что другая часть программного обеспечения не будет использовать файл, который я мог бы загружать, я просто создал на сервере другой каталог, который программа не отслеживала, и загрузил туда файлы. После того как файлы были завершены, я выполнил команду перемещения, чтобы переместить файлы в отслеживаемый каталог, и, поскольку перемещение — это атомарная операция в файловой системе, поэтому она безопасна для состояния гонки.
Других решений пока нет …