У меня есть функция, которая должна создавать резервную копию исходной папки путем копирования всех файлов из исходного в целевую папку. Функция использует цикл while, управляемый FindFirstFile
/ 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 поиска / копирования, которые работают более надежно?
Вероятно, это связано с тем, что SMB 2.0 в Windows поддерживает кэш, который обновляется только каждые 10 секунд.
Увидеть этот блог статья для получения дополнительной информации и программных решений.
Говорится:
Это связано с локальным кэшированием на стороне клиента с
SMB 2.0. Когда сеанс SMB 2.0 создан, локальный кеш
будет доступна на стороне клиента, которая будет обновлена после
каждые 10 секунд по умолчанию. Любой дальнейший запрос к файлу существует
будет проверяться с помощью этого локального кэша, а не идти к
общий доступ к серверу Итак, если локальный кеш построен на клиенте и на сервере
поделиться новый файл создан, локальный кэш не был признан недействительным и
не синхронизирован с общим ресурсом сервера, дальнейший запрос на проверку
существование нового файла не удастся. Это первопричина, но по замыслу. Если
локальный кеш обновляется и синхронизируется с общим ресурсом сервера, запрос будет
быть успешным.
Для разрешения / обхода в связанной статье упоминается:
Как мне управлять временем жизни локального кэша?
Вы можете создать разделы реестра ниже, чтобы управлять временем жизни кэша.
Под
HKEY_LOCAL_MACHINE \ SYSTEM \ CurrentControlSet \ Services \ LanmanWorkstation \ Параметры:
FileInfoCacheLifetime
FileNotFoundCacheLifetime
DirectoryCacheLifetime
Все они имеют тип REG_DWORD в секундах.
Программный обходной путь?
Зарегистрируйтесь для получения уведомлений об изменениях каталогов или файлов с помощью Win32 API.
Используйте API функции FindFirstChangeNotification (Windows) для регистрации
изменения.