我有一个功能,应该通过将所有文件从源文件夹复制到目标文件夹来创建源文件夹的备份。该函数使用由 FindFirstFile
驱动的 while 循环/FindNextFile
, 然后调用 CopyFile
对于 Find...
找到的每个文件功能。
现在,当源文件夹是 SMB 网络路径时(无论我使用映射驱动器还是 UNC 路径),有时会发生 FindNextFile
“看到”一个文件,但是 CopyFile
拒绝复制文件。错误代码为 2,即 ERROR_FILE_NOT_FOUND
.
我觉得这难以置信,所以我给 _access
添加了一个电话到检查文件是否存在的备份功能 CopyFile
叫做。结果与 CopyFile
相同,即 _access
报告文件不存在(返回代码 -1 且 errno
为 2,即 ENOENT
)。
所以我的主要问题是:FindFirstFile
怎么可能/FindNextFile
“看到”网络文件夹上的文件既不 CopyFile
也不_access
能看到吗?
附加信息/诊断:
- 有问题的文件是在运行备份功能之前立即创建的文件。具体来说,它是这样工作的:在客户端机器上运行的进程与在服务器机器上运行的进程有网络连接。客户端进程告诉服务器进程创建文件。这应该是同步工作的:只有在服务器进程确认它已经创建了文件后,客户端进程才会继续执行备份。
- 我在备份功能中添加了重试机制。有了这个,
CopyFile
和_access
重试约 4 秒后突然开始看到有问题的文件。这向我表明确实存在某种网络延迟。看起来好像FindFirstFile
/FindNextFile
访问不同于CopyFile
的网络路径/_access
.
不幸的是,我对此的研究没有发现任何有用的信息,所以我只能推测。如果FindFirstFile
/FindNextFile
/CopyFile
确实不能很好地协同工作,您知道另一组工作更可靠的查找/复制 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.
对于解决/解决方法,链接文章提到:
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.
关于c++ - 为什么 FindFirstFile/FindNextFile 有时会看到网络文件夹中的文件,而 CopyFile 却看不到?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29798025/