为什么 FindFirstFile / FindNextFile 有时会看到网络文件夹中的文件,但 CopyFile 却看不到?
Why do FindFirstFile / FindNextFile sometimes see a file on a network folder, but CopyFile does not?
我有一个功能,应该通过将所有文件从源文件夹复制到目标文件夹来创建源文件夹的备份。该函数使用由 FindFirstFile
/ FindNextFile
驱动的 while 循环,然后为 Find...
函数找到的每个文件调用 CopyFile
。
现在当源文件夹是一个SMB网络路径时(不管我使用的是映射驱动器还是UNC路径),有时会发生FindNextFile
"sees"一个文件,但是CopyFile
拒绝复制文件。错误码为2,即ERROR_FILE_NOT_FOUND
.
我觉得这难以置信,所以我在调用 CopyFile
之前向备份函数添加了对 _access
的调用,以检查文件是否存在。结果与 CopyFile
相同,即 _access
报告文件不存在(return 代码 -1 且 errno
为 2,即 ENOENT
).
所以我的主要问题是:网络文件夹中的 FindFirstFile
/ FindNextFile
"sees" 文件怎么可能既不是 CopyFile
也不是 _access
可以看到吗?
附加信息/诊断:
- 有问题的文件是在备份功能 运行 之前立即创建的文件。具体来说,它是这样工作的:客户端计算机上 运行s 的进程与服务器计算机上 运行s 的进程有网络连接。客户端进程告诉服务器进程创建文件。这应该是同步工作的:只有在服务器进程确认它已经创建了文件之后,客户端进程才会继续执行备份。
- 我在备份功能中加入了重试机制。有了这个,
CopyFile
和 _access
在重试大约 4 秒后突然开始看到有问题的文件。这向我表明确实存在某种网络延迟。似乎 FindFirstFile
/ FindNextFile
访问网络路径不同于 CopyFile
/ _access
。
不幸的是,我对此进行的研究没有找到任何有用的信息,所以我只能推测。如果 FindFirstFile
/ FindNextFile
/ CopyFile
确实不能很好地协同工作,你知道另一组 find/copy API 函数更可靠吗?
这可能是因为 windows 上的 SMB 2.0 维护了一个缓存,该缓存仅每 10 秒刷新一次。
请参阅 this blog archive 文章了解更多信息和程序化解决方法。
File.Exists /_access / GetFileAttributes / FindFirstFile,FindNextFile / _stat behavior over SMB 2.0
What is really happening?
This is because of the local caching included on the client side with
SMB 2.0. When the SMB 2.0 session has been created, the local cache
will be available on the client side, which will be refreshed after
every 10 seconds by default. Any further request to the file exists
will be checked against this local cache rather than going to the
server share. So, if a local cache is built on client, and on server
share a new file is created, local cache has not been invalidated and
not in sync with server share, any further request for checking the
new file existence will fail.
This is root cause, but by design. If the local cache is updated and in sync with server share, request will be successful.
resolution/work左右,链接文章提到:
How do I control the local cache lifetime?
You can create registry keys below to control the cache lifetime.
Under HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\LanmanWorkstation\Parameters
:
- FileInfoCacheLifetime
- FileNotFoundCacheLifetime
- DirectoryCacheLifetime
They are all REG_DWORD type in seconds.
Programmatic workaround?
Register for directory or file change notifications using Win32 API.
Use FindFirstChangeNotification Function (Windows) API to register for changes.
我有一个功能,应该通过将所有文件从源文件夹复制到目标文件夹来创建源文件夹的备份。该函数使用由 FindFirstFile
/ FindNextFile
驱动的 while 循环,然后为 Find...
函数找到的每个文件调用 CopyFile
。
现在当源文件夹是一个SMB网络路径时(不管我使用的是映射驱动器还是UNC路径),有时会发生FindNextFile
"sees"一个文件,但是CopyFile
拒绝复制文件。错误码为2,即ERROR_FILE_NOT_FOUND
.
我觉得这难以置信,所以我在调用 CopyFile
之前向备份函数添加了对 _access
的调用,以检查文件是否存在。结果与 CopyFile
相同,即 _access
报告文件不存在(return 代码 -1 且 errno
为 2,即 ENOENT
).
所以我的主要问题是:网络文件夹中的 FindFirstFile
/ FindNextFile
"sees" 文件怎么可能既不是 CopyFile
也不是 _access
可以看到吗?
附加信息/诊断:
- 有问题的文件是在备份功能 运行 之前立即创建的文件。具体来说,它是这样工作的:客户端计算机上 运行s 的进程与服务器计算机上 运行s 的进程有网络连接。客户端进程告诉服务器进程创建文件。这应该是同步工作的:只有在服务器进程确认它已经创建了文件之后,客户端进程才会继续执行备份。
- 我在备份功能中加入了重试机制。有了这个,
CopyFile
和_access
在重试大约 4 秒后突然开始看到有问题的文件。这向我表明确实存在某种网络延迟。似乎FindFirstFile
/FindNextFile
访问网络路径不同于CopyFile
/_access
。
不幸的是,我对此进行的研究没有找到任何有用的信息,所以我只能推测。如果 FindFirstFile
/ FindNextFile
/ CopyFile
确实不能很好地协同工作,你知道另一组 find/copy API 函数更可靠吗?
这可能是因为 windows 上的 SMB 2.0 维护了一个缓存,该缓存仅每 10 秒刷新一次。
请参阅 this blog archive 文章了解更多信息和程序化解决方法。
File.Exists /_access / GetFileAttributes / FindFirstFile,FindNextFile / _stat behavior over SMB 2.0
What is really happening?
This is because of the local caching included on the client side with SMB 2.0. When the SMB 2.0 session has been created, the local cache will be available on the client side, which will be refreshed after every 10 seconds by default. Any further request to the file exists will be checked against this local cache rather than going to the server share. So, if a local cache is built on client, and on server share a new file is created, local cache has not been invalidated and not in sync with server share, any further request for checking the new file existence will fail.
This is root cause, but by design. If the local cache is updated and in sync with server share, request will be successful.
resolution/work左右,链接文章提到:
How do I control the local cache lifetime?
You can create registry keys below to control the cache lifetime.
UnderHKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\LanmanWorkstation\Parameters
:
- FileInfoCacheLifetime
- FileNotFoundCacheLifetime
- DirectoryCacheLifetime
They are all REG_DWORD type in seconds.
Programmatic workaround?
Register for directory or file change notifications using Win32 API.
Use FindFirstChangeNotification Function (Windows) API to register for changes.