如何在多用户文件管理系统中锁定文件

时间:2011-05-18 13:03:13

标签: c# .net winforms filesystems

我有一个程序(将副本部署到每个用户计算机),以便用户使用压缩(CAB文件)将文件存储在集中式文件服务器上。

添加文件时,用户需要将文件解压缩到自己的磁盘上,添加文件并将其压缩回服务器。因此,如果两个用户同时处理相同的压缩文件,则后面上载的文件将替换之前的文件并导致数据丢失。

我的防范策略是在用户提取压缩文件之前,程序会检查服务器上是否存在指定的临时文件。如果没有,程序将创建这样的临时文件以防止其他用户的干扰,并在上传后删除临时文件;如果是,程序将等到临时文件被删除。

有更好的方法吗?并且经常创建和删除空文件会损坏磁盘吗?

4 个答案:

答案 0 :(得分:2)

  

并且会经常创造和   删除空文件会损坏磁盘吗?

没有。如果您使用的是固态磁盘,则可以执行的写入次数存在理论上的限制(这是FLASH的继承限制)。但是,你极不可能达到这个极限。

  

有更好的方法吗

好吧,我会以不同的方式解决这个问题:

编写一个处理所有磁盘访问的Windows服务,并让您的客户端应用程序与该服务通信。因此,当客户端需要检索文件时,它将打开与服务的套接字连接并请求该文件,并将其保存在内存中或将其保存到本地磁盘。对客户端的文件本地副本执行任何修改(解压缩,添加/删除/更新文件,重新压缩等),并且当操作完成并且您已准备好保存(或提交源代码控制术语)时更改,打开与服务应用程序的另一个套接字连接(在服务器上运行),并将新文件内容作为二进制流发送。

然后,服务应用程序将处理加载并将文件保存到磁盘。这为您提供了许多额外的功能 - 服务器可以跟踪过去的版本(甚至可能将每个版本提交到svn或其他源控制系统),提供元数据,例如最新版本等等。

现在我正在考虑它,你可能最好只是将svn界面集成到你的应用程序中。 SharpSVN is a good library for this.

答案 1 :(得分:1)

创建临时文件来标记锁是一个可行且广泛使用的选项(不,这不会损坏磁盘)。另一种选择是独占打开压缩文件(或让其他进程只读取文件但不写入它)并在用户处理文件内容时保持文件打开。

答案 2 :(得分:1)

  

有更好的方法吗?

是。从你在这里写的,听起来你正在重新发明revision control。 也许您可以使用一些现成的版本控制系统? 或者至少可以重用这些系统中的一些代码? 或许你至少可以了解一下这些系统面临的问题,如何解决明显的问题导致非显而易见的问题,并尝试建立一个至少也能运作的系统?

我的理解是版本控制系统经历了几个阶段(见 原始维基上的"Edit Conflict Resolution",Portland Pattern Repository)。 大致按时间顺序排列:

  1. 主版本存储在服务器上。最后挽救胜利,导致神秘的数据丢失而没有任何警告。
  2. 主版本存储在服务器上。当我将副本提取到我的机器时,系统会在服务器上创建一个锁定文件。当我将更改推送到服务器(或取消)时,系统会删除该锁定文件。没有人可以在服务器上更改这些文件,因此我们已经解决了“神秘的数据丢失”问题,但是当我需要编辑一些其他人在长假离开之前签出的文件时,我们会感到无比沮丧。
  3. 主版本存储在服务器上。首先获得胜利(“乐观锁定”)。当我从服务器中提取最新版本时,它包含某种版本号。当我稍后将我的编辑推送到服务器时,如果我提取的版本号与服务器上的当前版本不匹配,则其他人先切入并更改了我之前的事情,系统会给出一些礼貌的消息告诉我这件事。理想情况下,我从服务器中提取最新版本并小心地将其与我的版本合并,然后将合并后的版本推送到服务器,一切都很棒。唉,一个不耐烦的人拉着最新的版本,用“他的”版本覆盖它,推出“他的”版本,导致数据丢失。
  4. 每个版本都以完整的链条存储在服务器上。 (像TortoiseSVN这样的集中版本控制就是这样的。)
  5. 每个版本都存储在每个本地工作目录中;有时连锁叉成2条链;有时两条链合并成一条链。 (像TortoiseHg这样的分布式版本控制工具就是这样的。)
  6. 所以听起来你正在做其他人从第一阶段搬到第二阶段时所做的事情。我想你可以慢慢地在每个阶段都按照自己的方式行事。 或者也许你可以跳到第4或第5阶段并节省每个人的时间?

答案 3 :(得分:0)

查看FileStream.Lock方法。引自MSDN:

  

阻止其他进程读取或写入FileStream   ...

     

锁定一系列文件流使锁定进程的线程可以独占访问该范围的文件流。