Pergunta

Observe que isso não é duplicado de Arquivo r/w bloqueio e desvincular. (A Plataforma Diferença. Operações de arquivos como bloqueio e exclusão têm semântica totalmente diferente, portanto, a sulação seria diferente).

Eu tenho o seguinte problema. Quero criar um armazenamento de sessão baseado em sistema de arquivos, onde cada dados da sessão é armazenado em um arquivo simples nomeado com IDs de sessão.

Eu quero seguir a API: write(sid,data,timeout), read(sid,data,timeout), remove(sid)Onde SID == Nome do arquivo, também quero ter algum tipo de GC que possa remover todas as sessões cronometradas.

Tarefa bastante simples se você trabalha com um processo único, mas absolutamente não trivial ao trabalhar com vários processos ou mesmo em pastas compartilhadas.

A solução mais simples que eu pensava foi:

write/read:
   hanlde=CreateFile
   LockFile(handle)
   read/write data
   UnlockFile(handle)
   CloseHanlde(handle)

GC (for each file in directory)
   hanlde=CreateFile
   LockFile(handle)
   check if timeout occured
     DeleteFile
   UnlockFile(handle)
   CloseHanlde(handle)

Mas afiak eu não posso ligar DeleteFile On Opened Locked File (diferentemente do UNIX, onde o bloqueio de arquivos não é obrigatório e a desvinculação é permitida para arquivos abertos.

Mas se eu colocar DeleteFile Fora do bloqueio do cenário ruim do loop pode acontecer

GC - CreateFile/LockFile/Unlock/CloseHandle,
write - oCreateFile/LockFile/WriteUpdatedData/Unlock/CloseHandle
GC - DeleteFile

Alguém tem uma ideia de como esse problema pode ser resolvido? Existem truques que permitem combinar travamento de arquivos e remoção de arquivos ou operação em arquivo Atomic (Win32)?

Notas:

  • Eu não quero usar o banco de dados,
  • Procuro uma solução para a API Win32 para NT 5.01 e acima

Obrigado.

Foi útil?

Solução

Eu realmente não entendo como isso deve funcionar. No entanto, é possível excluir um arquivo aberto por outro processo. O processo que cria o arquivo deve usar o sinalizador File_Share_Delete para o argumento DWSharemode de createfile (). Uma chamada de deletefile () subsequente será bem -sucedida. Na verdade, o arquivo não é removido do sistema de arquivos até que o último identificador seja fechado.

Outras dicas

Atualmente, você tem dados no registro que permitem que o GC determine se o registro está cronometrado. Que tal estender as informações de limpeza com um sinalizador "ToolateWealReadyTimeditout".

 GC sets TooLateWeAlreadyTimedItOut = true
 Release lock
    <== writer comes in here, sees the "TooLate" flag and so does not write
 GC deletes

Em outras palavras, estamos usando uma espécie de abordagem otimista de bloqueio. Isso requer alguma complexidade adicional no escritor, mas agora você não depende de nenhuma ruína do SS-Specifc.

Não estou claro o que acontece no caso:

 GC checks timeout
 GC deletes
 Writer attempts write, and finds no file ...

Tudo o que você planejou para este caso também pode ser usado no caso "ferramenta"

Editado para adicionar:

Você disse que é válido para que essa sequência ocorra:

 GC Deletes
 (Very slightly later) Writer attempts a write, sees no file, creates a new one

O escritor pode tratar a bandeira "ferramenta" como idêntica a este caso. Apenas cria um novo Arquivo, com um nome diferente, use um número de versão como parte de seu nome. A abertura de um arquivo de sessão na primeira vez requer uma pesquisa de diretório, mas você pode guardar o nome mais recente na sessão.

Isso assume que só pode haver um tópico de escritor para uma determinada sessão ou que possamos mediar entre dois threads de escritores criando o arquivo, mas isso deve ser verdadeiro para que seu caso simples de GC/Writer funcione.

Para Windows, você pode usar o FILE_FLAG_DELETE_ON_CLOSE Opção para createfile - Isso fará com que o arquivo seja excluído quando você fechar o identificador. Mas não tenho certeza se isso satisfaz sua semântica (porque não acredito que você possa limpar o atributo Delete-on-Close.

Aqui está outro pensamento. Que tal renomear o arquivo antes de excluí -lo? Você simplesmente não pode fechar a janela onde a gravação entra depois que você decidiu excluir o arquivo, mas e se você renunciar ao arquivo antes de excluí -lo? Então, quando a gravação entrar, verá que o arquivo de sessão não existe e o recrie.

A principal coisa a ter em mente é que você simplesmente não pode fechar a janela em questão. IMHO Existem duas soluções:

  1. Adicionando uma bandeira como o DJNA mencionado ou
  2. Exigir que seja adquirida uma adquirida uma MUTEX por sessão, que tem o efeito colateral infeliz de serializar gravações na sessão.

Qual é a desvantagem de ter um sinalizador de ferramentas? Em outras palavras, o que dá errado se você excluir o arquivo prematuramente? Depois de todo o seu sistema ter que lidar com o arquivo não estar presente ...

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