Установка времени последнего изменения каталога, открытого для ReadDirectoryChangesW - PullRequest
2 голосов
/ 17 июля 2009

У меня есть Java-программа, которая должна отслеживать дерево каталогов на предмет изменений. У меня есть код JNI, который использует ReadDirectoryChangesW(). Каталог открывается как:

HANDLE dirHandle = CreateFile(
    path, FILE_LIST_DIRECTORY, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
    OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL
);

и затем я передаю dirHandle на ReadDirectoryChangesW(). Все это прекрасно работает.

Проблема в том, что другие части кода (на стороне Java) используют File.setLastModified() для «касания» файлов или каталогов (обновите их метки времени, чтобы они были «сейчас»). Это обычно работает; однако, это терпит неудачу, когда он пытался "коснуться" каталога, который был открыт, используя CreateFile().

Чтобы увидеть, какая ошибка Windows на самом деле происходит, я посмотрел на исходный код JDK для File.setLastModified() и переопределил его в своем собственном коде с добавлением печати ошибки из GetLastError(); ошибка:

ERROR_SHARING_VIOLATION (error 32)
"The process cannot access the file because it is being used by another process."

WTF? Это тот же процесс. Я даже передал FILE_SHARE_READ и FILE_SHARE_WRITE на CreateFile().

Есть ли способ заставить эту работу?

Подробнее

Реализация собственного кода File.setLastModified() в JDK делает:

h = CreateFileW(pathbuf, GENERIC_WRITE, 0, NULL, OPEN_EXISTING,
                FILE_ATTRIBUTE_NORMAL | FILE_FLAG_BACKUP_SEMANTICS, 0);

Если я изменю первый 0 на FILE_SHARE_READ | FILE_SHARE_WRITE, все будет работать. Таким образом, кажется, что реализация JDK немного сломана. (

Таким образом, мой вопрос теперь звучит так: есть ли способ сделать эту работу без необходимости использовать мою (пере) реализацию File.setLastModified()?

1 Ответ

1 голос
/ 18 июля 2009

Хотя в данном случае сообщение об ошибке немного вводит в заблуждение, вы видите нормальное поведение.

Открывая каталог с dwShareMode, установленным на ноль, JDK фактически запрашивает исключительный доступ, что приведет к сбою любой другой попытки доступа с ошибкой нарушения общего доступа. Это в равной степени относится и к доступам от других процессов и из вашего собственного процесса.

Документация CreateFile описывает параметр dwShareMode:

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

Вы не можете запросить режим общего доступа, который конфликтует с режимом доступа, указанным в существующем запросе с открытым дескриптором. Сбой CreateFile и функция GetLastError вернут ERROR_SHARING_VIOLATION.

Похоже, вы ответили на свой вопрос: вам нужна пользовательская функция setLastModified, которая задает FILE_SHARE_READ | FILE_SHARE_WRITE при доступе к каталогу.

...