请注意,这与File r/w locking and unlink不重复。 (差异 - 平台。锁定和删除等文件的操作具有完全不同的语义,因此硫化会有所不同。)
我有以下问题。我想创建一个基于文件系统的会话存储,其中每个会话数据都存储在以会话ID命名的简单文件中。
我想要关注API:write(sid,data,timeout)
,read(sid,data,timeout)
,remove(sid)
其中sid ==文件名,我也希望有某种GC可以删除所有超时会话。
如果你使用单个进程,但是在处理多个进程甚至是共享文件夹时绝对不是一件容易的事,这是一项非常简单的任务。
我想到的最简单的解决方案是:
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)
但AFIAK我无法在打开的锁定文件上调用DeleteFile
(与Unix中的文件锁定不同)
不是强制性的,打开的文件允许取消链接。
但如果我将DeleteFile
置于锁定循环之外,可能会发生错误情况
GC - CreateFile/LockFile/Unlock/CloseHandle,
write - oCreateFile/LockFile/WriteUpdatedData/Unlock/CloseHandle
GC - DeleteFile
有人知道如何解决这个问题吗?有没有允许的技巧 合并文件锁定和文件删除或对文件原子(Win32)进行操作?
备注:
感谢。
答案 0 :(得分:2)
我真的不明白这是怎么回事。但是,可以删除由另一个进程打开的文件。创建文件的过程必须使用FILE_SHARE_DELETE标志来创建CreateFile()的dwShareMode参数。随后的DeleteFile()调用将成功。该文件实际上不会从文件系统中删除,直到它的最后一个句柄关闭。
答案 1 :(得分:1)
您当前在记录中有数据,允许GC确定记录是否超时。如何使用“TooLateWeAlreadyTimedItOut”标志扩展该清洁信息。
GC sets TooLateWeAlreadyTimedItOut = true
Release lock
<== writer comes in here, sees the "TooLate" flag and so does not write
GC deletes
换句话说,我们正在使用一种乐观的锁定方法。这确实需要Writer中的一些额外的复杂性,但现在你不依赖于任何特定于操作系统的皱纹。
我不清楚案件中会发生什么:
GC checks timeout
GC deletes
Writer attempts write, and finds no file ...
无论你为此案例计划的是什么,也可以在“TooLate”案例中使用
编辑添加:
你已经说过这个序列发生是有效的:
GC Deletes
(Very slightly later) Writer attempts a write, sees no file, creates a new one
作者可以将“tooLate”标志视为与此案例相同。它只是创建一个具有不同名称的 new 文件,使用版本号作为其名称的尾随部分。首次打开会话文件需要进行目录搜索,但是您可以在会话中存储最新的名称。
这确实假定给定会话只能有一个Writer线程,或者我们可以在创建文件的两个Writer线程之间进行调解,但是对于简单的GC / Writer案例来说,这必须是正确的。
答案 2 :(得分:0)
对于Windows,您可以使用CreateFile的FILE_FLAG_DELETE_ON_CLOSE选项 - 这将导致在关闭句柄时删除文件。但我不确定这是否满足您的语义(因为我不相信您可以清除关闭时删除属性。
这是另一个想法。在删除文件之前重命名文件怎么样?在您决定删除文件后,您根本无法关闭写入的窗口,但如果在删除文件之前重命名该文件会怎么样?然后当写入时,它会看到会话文件不存在并重新创建它。
要记住的关键是你无法关闭有问题的窗口。恕我直言有两种解决方案:
拥有TooLate标志的缺点是什么?换句话说,如果过早删除文件会出现什么问题?毕竟你的系统必须处理文件不存在......