Windows Projected File System только для чтения? - PullRequest
2 голосов
/ 08 марта 2019

Я попытался поэкспериментировать с Projected File System для реализации оперативного диска в пользовательском режиме (ранее я использовал Dokan). У меня два вопроса:

  1. Это проекция только для чтения? Я не смог найти ничего отправленного мне уведомления при открытии файла, скажем, в Блокноте и записи в него.

  2. Действительно ли файл создается на диске после использования PrjWriteFileData ()? Из того, что я понял, да.

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

1 Ответ

1 голос
/ 23 мая 2019

Краткий ответ:

  1. Это не только для чтения, но вы не можете записать свои файлы напрямую в "исходную" файловую систему через проекцию.
  2. WriteFileData метод используется для заполнения файлов-заполнителей в «чистой» (проектируемой) файловой системе, поэтому он не влияет на «исходную» файловую систему.

Длинный ответ:

Как указано в комментарии @ zett42, ProjFS в основном была разработана как удаленная файловая система git. Итак, основная цель любой системы управления версиями файлов - обрабатывать несколько версий файлов. Отсюда возникает вопрос - нужно ли перезаписывать файл внутри удаленного репозитория при записи файла ProjFS? Это было бы катастрофично. При работе с git вы всегда пишете файлы локально, и они не синхронизируются, пока вы не отправите изменения в удаленный репозиторий.

При перечислении файлов ничего не записывается в локальную файловую систему. Из документации ProjFS:

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

Только после открытия файла ProjFS создает для него «местозаполнитель» в локальной файловой системе - я предполагаю, что это файл со специальной структурой (не реальной).

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

Что значит "гидратированный"? Скорее всего, он представляет собой особую структуру данных, частично заполненную реальными данными. Я бы представил заполнитель как губку, частично заполненную данными.

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

Только после обновления файла (изменения). Это больше не заполнитель - он становится «Полный файл / каталог»:

Для файлов: содержимое файла (первичный поток данных) было изменено. Файл больше не является кешем своего состояния в хранилище провайдера. Файлы, которые были созданы в локальной файловой системе (т.е. не существует в магазине провайдера вообще) также считается полные файлы.

Для каталогов: каталоги, созданные в локальном файле система (т.е. вообще не существует в магазине провайдера) считается полными каталогами. Каталог, который был создан на диск как заполнитель никогда не становится полным каталогом.

Это означает, что при первой записи заполнитель заменяется реальным файлом в локальной FS. Но как синхронизировать «удаленный» файл с измененным? (1)

Когда провайдер вызывает PrjWritePlaceholderInfo для записи заполнитель информации, он предоставляет ContentID в VersionInfo член аргумента placeholderInfo. Поставщик должен затем запишите, что заполнитель для этого файла или каталога был создан в этот взгляд.

Уведомление " Поставщик должен затем записать, что заполнитель для этого файла ". Это означает, что для последующей синхронизации файла с представлением правильного мы должны запомнить, с какой версией связан измененный файл. Представьте, что мы находимся в репозитории git и меняем ветку. В этом случае мы можем обновить один файл несколько раз в разных ветках. Теперь, почему и когда провайдер звонит PrjWritePlaceholderInfo?

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

Еще раз представьте себепереключение веток в git-репозитории;Вы должны обновить файл, если он отличается в другой ветке.Продолжая отвечать на вопрос (1).Imaging вы хотите сделать "толчок" из определенной ветви.Прежде всего, вы должны знать, какие файлы изменены.Если вы не записали информацию о заполнителе во время изменения файла, вы не сможете сделать это правильно (по крайней мере, для примера с git-репозиторием).

Помните, что заполнитель заменяется реальным файлом вмодификация?ProjFS имеет событие OnNotifyFileHandleClosedFileModifiedOrDeleted.Вот подпись обратного вызова:

public void NotifyFileHandleClosedFileModifiedOrDeletedCallback(
    string relativePath,
    bool isDirectory,
    bool isFileModified,
    bool isFileDeleted,
    uint triggeringProcessId,
    string triggeringProcessImageFileName)

Для нашего понимания наиболее важным параметром для нас является relativePath.Он будет содержать имя измененного файла в файловой системе «нуля» (проецируется).Здесь вы также знаете, что файл является реальным файлом (а не заполнителем) и записывается на диск (то есть вы не сможете перехватить вызов до записи файла).Теперь вы можете скопировать его в нужное место (или сделать это позже) - это зависит от ваших целей.

Отвечая на вопрос № 2, похоже, что PrjWriteFileData используется только для заполнения "чистой" файловой системыи вы не можете использовать его для обновления «исходной» файловой системы.

Приложения:

Что касается приложений, вы все равно можете реализовать удаленную файловую систему (вместо использованияDokan), но все записи будут кэшироваться локально, а не записываться напрямую в удаленное местоположение.Пара вариантов использования:

  1. Распределенные файловые системы
  2. Online Drive Client
  3. Файловая система «Диспетчер» (например, вы можете записывать файлы в разныепапки в зависимости от конкретных условий)
  4. Система управления версиями файлов (например, вы можете сохранить разные версии одного и того же файла после изменения)
  5. Зеркальное отображение данных из вашего приложения в файловую систему (дляНапример, вы можете «проецировать» текстовый файл с отступами на папки, подпапки и файлы)

PS: я не знаю ни одного недокументированного API, но с моей точки зрения (соответственнос документацией) мы не можем использовать ProjFS для таких целей, как виртуальный диск или записывать файлы непосредственно в «исходную» файловую систему без предварительной записи их в «локальную» файловую систему.

...