microsoft / ProjFS-Managed-API

A managed-code API for the Windows Projected File System
Other
142 stars 34 forks source link

PrjGetOnDiskFileState not available? #49

Closed FeralSquid closed 4 years ago

FeralSquid commented 4 years ago

Hello,

I need a way to tell if a given random file path string from a user/client application is as "real"/local file or if it is virtual (whether hydrated or not) quickly.

From the MSDN docs, it sounds like PrjGetOnDiskFileState() is exactly what I want here, but it doesn't appear to be exposed through the managed layer ... am I overlooking it, or is there a reason it was omitted?

I can just call File.Exists(), I suppose, but that seems pretty wasteful when I'm going to be in the code that owns the VirtualizationInstance anyway.

I could also track all locally created files via callbacks, I suppose, but then I'd have to persist that and keep it in memory, and it could be millions in degenerate cases, so definitely isn't ideal.

Thanks, Brandon

P.S. - I'm just starting on a project using this and so far it is pretty sweet and easy to work with! ;)

Debee416 commented 4 years ago

Hi, the method you are looking for is Microsoft.Windows.ProjFS.Utils.TryGetOnDiskFileState().

D.

FeralSquid commented 4 years ago

Ah, there it is!

Thanks

cgallred commented 4 years ago

@FeralSquid note that TryGetOnDiskFileState() will never return a state indicating "virtual"; if you look in Microsoft.Windows.ProjFS.OnDiskFileState you'll see that there is no "virtual" state. That's because a virtual file has no on-disk state. Calling TryGetOnDiskFileState() on a path for a virtual item will cause a request to the provider to hydrate a placeholder (which is why there's a warning that a running provider needs to be cautious calling it; the idea is that it is mainly intended for utility apps).

If you just want to tell the difference between virtual and local (in any state), you can enumerate the item's parent directory. If the FILE_ATTRIBUTE_RECALL_ON_OPEN bit is set for that item in the enumeration then it is virtual. Again, you may need to be careful if the provider is performing the enumeration since it will receive callbacks to supply the contents of the enumeration it is itself requesting.

Note that a provider that supports view changes would be expected to keep track of which items it has hydrated, otherwise it would be difficult and/or expensive for the provider to determine which local items needed to be updated or deleted in the view change.

FeralSquid commented 4 years ago

ah ok, thanks for that detail. I saw the note in the documentation so was trying to test it out to see the exact behavior.

I'm working on a companion piece that enables retrieving the checksum for a given file without hydrating it, as we have many apps that require checksums to then decide if cached work can be used, and if so we don't need to hydrate the local file (which is one of the potential big wins here).

So, when I get a request for a checksum of a random file path, I need to determine if it is a real local file (and if so, calc the checksum from it), else fetch the checksum from my virtual backing store. This means that keeping track of hydrated files isn't enough here (hopefully the file isn't hydrated at this point).

I was hoping there was a way for me to quickly check and see if a file is on the local disk without triggering ProjFS callbacks that would require more expensive and largely unnecessary work, but I can just request the file attributes for the specific file (on a separate thread to avoid deadlock) and check that way if that is the best available solution.

Thanks!

On Wed, Jul 22, 2020 at 11:47 AM Christian Allred notifications@github.com wrote:

@FeralSquid https://github.com/FeralSquid note that TryGetOnDiskFileState() will never return a state indicating "virtual"; if you look in Microsoft.Windows.ProjFS.OnDiskFileState https://github.com/microsoft/ProjFS-Managed-API/blob/master/ProjectedFSLib.Managed.API/OnDiskFileState.h you'll see that there is no "virtual" state. That's because a virtual file has no on-disk state. Calling TryGetOnDiskFileState() on a path for a virtual item will cause a request to the provider to hydrate a placeholder (which is why there's a warning that a running provider needs to be cautious calling it; the idea is that it is mainly intended for utility apps).

If you just want to tell the difference between virtual and local (in any state), you can enumerate the item's parent directory. If the FILE_ATTRIBUTE_RECALL_ON_OPEN https://docs.microsoft.com/en-us/windows/win32/fileio/file-attribute-constants bit is set for that item in the enumeration then it is virtual. Again, you may need to be careful if the provider is performing the enumeration since it will receive callbacks to supply the contents of the enumeration it is itself requesting.

Note that a provider that supports view changes https://docs.microsoft.com/en-us/windows/win32/projfs/handling-view-changes would be expected to keep track of which items it has hydrated, otherwise it would be difficult and/or expensive for the provider to determine which local items needed to be updated or deleted in the view change.

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/microsoft/ProjFS-Managed-API/issues/49#issuecomment-662623337, or unsubscribe https://github.com/notifications/unsubscribe-auth/AQJ2NHE7MBFNTNEISRNLHTTR44X5NANCNFSM4PEF2NWQ .