Pergunta

Eu hava um Java programa que precisa para monitorar uma árvore de diretórios para mudanças. Eu tenho o código JNI que usos ReadDirectoryChangesW(). O diretório é aberto como:

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

e então eu passar dirHandle para ReadDirectoryChangesW(). Tudo isso funciona muito bem.

O problema é que outras partes do código (no lado do Java) uso File.setLastModified() para arquivos "toque" ou diretórios (actualizar as suas marcas de tempo para ser "agora"). Isso geralmente funciona; no entanto, ele falha quando tentou "toque" o diretório que foi aberto usando CreateFile().

Para ver o erro do Windows está realmente acontecendo, eu olhei para a fonte JDK para File.setLastModified() e reimplemented-lo em meu próprio código com a adição de imprimir o erro de GetLastError(); o erro é:

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

WTF? É o mesma processo. Eu até passou FILE_SHARE_READ e FILE_SHARE_WRITE para CreateFile().

Existe uma maneira de fazer este trabalho?

Mais informações

A implementação de código nativo do File.setLastModified() no JDK faz um:

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

Se eu mudar o primeiro 0 para FILE_SHARE_READ | FILE_SHARE_WRITE, tudo funciona. Assim, parece que a implementação JDK é um pouco quebrado. : (

Assim, a minha pergunta agora é:? Existe uma maneira de fazer este trabalho sem ter que usar o meu próprio (re) implantação de File.setLastModified()

Foi útil?

Solução

Embora a mensagem de erro é um pouco enganador, neste caso, o que você está vendo é um comportamento normal.

Ao abrir o diretório com o conjunto dwShareMode a zero, o JDK é, com efeito, pedindo acesso exclusivo, o que fará com que qualquer outra tentativa de acesso a falhar com um erro de violação de compartilhamento. Isso se aplica igualmente aos acessos de outros processos e de dentro do seu próprio processo.

O CreateFile documentação descreve o parâmetro dwShareMode:

Se este parâmetro é zero e CreateFile sucedido, o arquivo ou dispositivo não pode ser compartilhado e não pode ser aberta novamente até que o identificador para o arquivo ou dispositivo está fechado.

Você não pode solicitar um modo de compartilhamento que os conflitos com o modo de acesso que está especificado em um pedido existente que tem um identificador aberto. CreateFile iria falhar ea função GetLastError voltaria ERROR_SHARING_VIOLATION.

Assim, parece que você respondeu a sua própria pergunta:. Você precisa de uma função setLastModified personalizado que especifica FILE_SHARE_READ | FILE_SHARE_WRITE ao acessar o diretório

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top