Изящное чтение файлов без блокировки

Обзор Доску

изображения ниже 1000 x 750 px, ~130 kB JPEGs размещено на ImageShack.


Дополнительная Информация

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

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


Возможных Реализаций

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

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

  1. метод один (медленный):

    • прогулка /Foo дерево каталогов каждые N минут.

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

    • слияние изменений с FTP-сервером за пределами сайта.

  2. Способ второй:

    • Регистрация уведомлений об изменении каталога (например, с помощью ReadDirectoryChangesW из WinAPI, или FileSystemWatcher при использовании .NET).

    • журнал.

    • слияние изменений с Off-site FTP server каждые N протокол.

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


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

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


Возможное Решение

самым простым решением вышеуказанной проблемы было бы создать копию файла(ов) в другом месте файловой системы и передать их "снимки" без помех.

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

такое решение кажется некрасивым, хотя, и я уверен, что есть лучший способ справиться с этим типом проблема.

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


вопросы

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

меня интересуют чистые решения, которые не требуют переборщил со сложностью их реализации. Возможно, я пропустил что-то в WinAPI, что обрабатывает эту проблему изящно?

я еще не решил, что буду писать, но мне удобно с: C, C++, C#, D и Perl.

2 ответов


после обсуждения в комментариях мое предложение будет выглядеть так:

  • создайте раздел на сервере данных, около 5 ГБ для обеспечения безопасности.
  • создайте проект службы Windows на C#, который будет контролировать ваш драйвер данных / местоположение.
  • после изменения файла создайте локальную копию файла, содержащую ту же структуру каталогов, и поместите ее в новый раздел.
  • создайте другую службу, которая будет делать следующий:
    • Мониторинг Использования Полосы Пропускания
    • мониторинг создания файлов во временном разделе.
    • передача нескольких файлов одновременно (использование потоков) на ваш FTP-сервер, соблюдая использование полосы пропускания в настоящее время, уменьшая / увеличивая рабочие потоки в зависимости от сетевого трафика.
    • удалите файлы из раздела, которые были успешно переданы.

Итак, диска:

  • C: Установка Windows
  • D: Общий Доступ К Хранилищу
  • X: Временный Раздел

тогда у вас будут следующие услуги:

  • LocalMirrorService - часы D: и копии X: со структурой dir
  • TransferClientService - перемещение файлов из X: на FTP-сервер, удаляет из X:
    • также использует несколько потоков для перемещения кратных и мониторы полосы пропускания.

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

когда пользователь редактирует документ в Microsoft Word, например, файл изменится на общий ресурс, и он может быть скопирован в X: даже если потребитель все еще работает на ем, внутри windows там будет API посмотреть, если дескриптор файла по-прежнему открыт пользователем, если это так, то вы можете просто создать крюк, чтобы смотреть, когда пользователь фактически закрывает документ, так что все там изменения завершены, то вы можете перейти на диск X:.

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


для тех, кто в подобной ситуации (я предполагаю, что человек, задавший вопрос, давно реализовал решение), я бы предложил реализацию rsync.

rsync.net s Агент Резервного Копирования Windows делает то, что описано в методе 1, и также может запускаться как служба (см. "Дополнительные Функции"). Хотя я не совсем уверен, что он имеет встроенное ограничение пропускной способности...

другое (возможно, лучшее) решение, которое тут есть ограничение полосы пропускания Duplicati. Он также правильно создает резервные копии в настоящее время-открытые или заблокированные файлы. Использует SharpRSync, управляемую реализацию rsync, для своего бэкэнда. С открытым исходным кодом тоже, что всегда плюс!