请注意,这不是重复的 文件读/写锁定和取消链接. 。(区别 - 平台。文件的操作(如锁定和删除)具有完全不同的语义,因此结果会不同)。

我有以下问题。我想创建一个基于文件系统的会话存储,其中每个会话数据都存储在以会话 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)

但我不能打电话 DeleteFile 在打开的锁定文件上(与UNIX不同,该文件不强制性锁定,并且打开文件允许UNINK。

但如果我把 DeleteFile 在锁定循环之外可能会发生不良情况

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

有人知道如何解决这样的问题吗?有什么技巧可以允许 将文件锁定和文件删除结合起来,还是在文件原子 (Win32) 上进行操作?

笔记:

  • 我不想使用数据库,
  • 我正在寻找适用于 NT 5.01 及更高版本的 Win32 API 的解决方案

谢谢。

有帮助吗?

解决方案

我真的不明白这应该如何运作。但是,删除由另一个进程打开的文件是可能的。创建文件的进程必须使用 CreateFile() 的 dwShareMode 参数的 FILE_SHARE_DELETE 标志。随后的DeleteFile() 调用将会成功。在关闭文件的最后一个句柄之前,该文件实际上不会从文件系统中删除。

其他提示

当前记录中的数据允许 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”标志视为与本例相同。它只是创建一个 新的 文件,具有不同的名称,使用版本号作为其名称的尾部部分。第一次打开会话文件需要进行目录搜索,但随后您可以在会话中存储最新的名称。

这确实假设给定会话只能有一个 Writer 线程,或者我们可以在创建文件的两个 Writer 线程之间进行调解,但这对于您的简单 GC/Writer 案例来说必须是正确的。

对于 Windows,您可以使用 FILE_FLAG_DELETE_ON_CLOSE CreateFile 的选项 - 这将导致在关闭句柄时删除文件。但我不确定这是否满足您的语义(因为我不相信您可以清除关闭时删除属性。

这是另一个想法。在删除文件之前重命名该文件怎么样?在决定删除文件后,您根本无法关闭写入的窗口,但是如果您在删除文件之前重命名该文件怎么办?然后,当写入进来时,它会发现会话文件不存在并重新创建它。

要记住的关键是您根本无法关闭有问题的窗口。恕我直言,有两种解决方案:

  1. 添加像 djna 提到的标志或
  2. 要求获取名为互斥体的每个会话,这会产生序列化会话写入的不幸副作用。

使用 TooLate 标志有什么缺点?换句话说,如果过早删除文件会出现什么问题?毕竟您的系统必须处理不存在的文件......

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top