2009-03-20 2 views
5

Я выполняю очень вычислительную интенсивную научную работу, которая время от времени выплевывает результаты. Работа в основном заключается в том, чтобы просто имитировать одно и то же целое множество раз, поэтому он разделен между несколькими компьютерами, использующими разные ОС. Я хотел бы направить вывод из всех этих экземпляров в один и тот же файл, так как все компьютеры могут видеть одну и ту же файловую систему через NFS/Samba. Вот ограничения:Платформа независимая блокировка файлов?

  1. Должен разрешать безопасные одновременные добавления. Должен блокироваться, если какой-либо другой экземпляр на другом компьютере в настоящее время добавляется к файлу.
  2. Выступление не кол-во. I/O для каждого экземпляра - всего несколько байтов в минуту.
  3. Простота в использовании. Вся суть этого (помимо чистого любопытства) заключается в том, что я могу прекратить записывать каждый экземпляр в другой файл и объединять эти файлы вручную.
  4. Нельзя зависеть от деталей файловой системы. Должен работать с неизвестной файловой системой на NFS или Samba mount.

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

ответ

7

Над NFS вы столкнулись с некоторыми проблемами с кешированием и устаревшими данными на стороне клиента. Я написал независимый от ОС модуль блокировки для работы над NFS раньше. Простая идея создания файла [datafile] .lock не работает над NFS. Основная идея, чтобы обойти это, - создать файл блокировки [файл данных] .lock, который, если данный файл означает, НЕ заблокирован, а процесс, который хочет получить блокировку, переименовывает файл в другое имя, например [datafile] .lock. [ имя хоста]. [PID]. Переименование - достаточно атомная операция, которая достаточно хорошо работает над NFS, чтобы гарантировать исключительность блокировки. Остальное - это, в основном, куча отказоустойчивых циклов, проверка ошибок и поиск блокировки в случае, если процесс замирает, прежде чем освободить блокировку и переименовать файл блокировки обратно в [файл данных] .lock

1

Я не знаю, D, но я использую файл мьютекса для выполнения работы. Вот некоторые псевдо-код, который вы могли бы найти полезным:

do { 
    // Try to create a new file to use as mutex. 
    // If it's already created, it will throw some kind of error. 
    mutex = create_file_for_writing('lock_file'); 
} while (mutex == null); 

// Open your log file and write results 
log_file = open_file_for_reading('the_log_file'); 
write(log_file, data); 
close_file(log_file); 

close_file(mutex); 
// Free mutex and allow other processes to create the same file. 
delete_file(mutex); 

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

+0

Вы, должно быть, пропустили ту часть, где он сказал, что ему нужна синхронизация между разными компьютерами. –

+0

И это решение не будет работать над NFS по его просьбе. –

+0

Почему бы не работать? Я не хочу писать файл локально на каждом компьютере, но в одном месте для всех. – Seb

2

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

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

Это используется в таких приложениях, как CVS в течение многих лет по многим платформам. Единственная проблема возникает в редких случаях, когда ваше приложение падает во время записи и перед удалением блокировки.

2

Блокировка файла с твист

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

Поскольку вы хотите иметь доступ к одному файлу на нескольких ПК, лучшим решением, о котором я могу думать, является просто указать идентификатор машины, которая в настоящее время записывается в файл данных.

Таким образом, последовательность записи в файл данных будет:

  1. Проверьте, есть ли блокировка файла присутствует

  2. Если есть файл блокировки, видеть, если я один владея им, проверяя, что его содержимое имеет мой идентификатор.
    Если это так, просто напишите в файл данных, затем удалите файл блокировки.
    Если это не так, просто подождите секунду или небольшой случайный промежуток времени и повторите весь цикл.

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

Наряду с идентификатором я записывал временную метку в файле блокировки и проверял, является ли она старше заданного значения таймаута.
Если временная метка слишком старая, предположим, что файл блокировки устарел и просто удаляет его, так как может произойти сбой одной из записей ПК в файл данных или может быть потеряно его соединение.

Другое решение

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

Проблемы с NFS

ОК, я добавил несколько вещей, потому что Иржи Klouda правильно указал, что NFS uses client-side caching, что приведет к фактическому файлу блокировки, находясь в неопределенном состоянии.

несколько способов решить эту проблему:

  • смонтировать каталог NFS с noac или sync вариантов. Это легко, но не полностью гарантирует согласованность данных между клиентом и сервером, хотя все равно могут возникать проблемы, хотя в вашем случае это может быть хорошо.

  • Открыть файл блокировки или файл данных, используя атрибуты O_DIRECT, O_SYNC или O_DSYNC. Это должно полностью отключить кеширование.
    Это снижает производительность, но обеспечивает согласованность.

  • Вы может быть в состоянии использовать flock() заблокировать файл данных, но его реализация пятнистая и вам нужно будет проверить, если ваша конкретная ОС на самом деле использует запирающий службу NFS. В противном случае он ничего не может сделать.
    Если файл данных заблокирован, то другой клиент, открывающий его для записи, потерпит неудачу.
    О да, и, похоже, он не работает на акциях SMB, поэтому, наверное, лучше всего просто забыть об этом.

  • Не используйте NFS и вместо этого используйте Samba: есть good article on the subject и почему NFS, вероятно, не лучший ответ на ваш сценарий использования.
    В этой статье вы также найдете различные способы блокировки файлов.

  • Решение Jiri также является хорошим.

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

Что-то другое

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

+1

Это решение, работая отлично на одном компьютере, будет работать в условиях гонки из-за кеширования на стороне клиента NFS. –

+0

Обратите внимание, что NFSv4 устраняет многие проблемы со старыми версиями протокола. – janneb

2

Почему бы просто не построить простой сервер, который находится между файлом и другими компьютерами?

Затем, если вы когда-либо хотели изменить формат данных, вам нужно было бы только изменить сервер, а не все клиенты.

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

+0

Или просто используйте базу данных и сохраните данные в правильной базе данных и проблемы с блокировкой. –

+0

У меня нет настроенной базы данных, и я не хочу ее настраивать, чтобы решить такую ​​простую проблему. – dsimcha

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