没有锁定的优雅文件阅读

时间:2011-02-19 22:43:40

标签: windows winapi filesystems synchronization locking

白板概述

以下图片是ImageShack上托管的1000 x 750 px, ~130 kB JPEGs


其他信息

我应该提到每个用户(客户端盒子)将直接在/Foo份额下工作。由于业务的性质,用户永远不需要同时查看或处理彼此的文档,因此这种性质的冲突永远不会成为问题。访问需要尽可能简单,这可能意味着将驱动器映射到各自的/Foo/username子目录。

此外,除了我的应用程序(内部和服务器上的应用程序)之外,没有人会直接使用FTP目录。


可能的实施

不幸的是,看起来我不能使用现成的工具,例如WinSCP,因为其他一些逻辑需要与流程密切相关。

我认为有两种简单的方法让我在内部完成上述工作。

  1. 方法一(慢):

    • 每N分钟走一次/Foo目录树。

    • 使用时间戳的组合(可以通过文件复制工具伪造,但在这种情况下不相关)和校验和来与前一棵树进行差异。

    • 将更改与异地FTP服务器合并。

  2. 方法二:

    • 注册目录更改通知(例如,使用WinAPI中的ReadDirectoryChangesW,或使用.NET时使用FileSystemWatcher

    • 记录更改。

    • 每隔N分钟与异地FTP服务器合并更改。

  3. 由于性能方面的考虑,我可能最终会使用第二种方法。


    问题

    由于此同步必须在工作时间进行,因此出现的第一个问题是在场外上传阶段。

    当我在异地传输文件时,我实际上需要阻止用户写入文件(例如,当我正在阅读时,使用CreateFileFILE_SHARE_READ或其他内容)它。他们办公室的互联网上行速度与他们正在使用的文件大小几乎没有对称,所以他们很可能会回到文件并尝试修改它,而我还在阅读它。 / p>


    可能的解决方案

    解决上述问题的最简单方法是在文件系统的其他位置创建相关文件的副本,并在不受干扰的情况下传输这些“快照”。

    这些人将使用的文件(有些将是二进制文件)相对较小,可能≤20MB,因此复制(因此暂时锁定)它们几乎是即时的。他们在我复制它的同一瞬间尝试写入文件的机会应该接近于零。

    这个解决方案看起来有点难看,而且我很确定有更好的方法来处理这类问题。

    我想到的一件事就是文件系统过滤器,它负责IRP级别的复制和同步,就像一些A / V所做的那样。然而,这对我的项目来说太过分了。


    问题

    这是我第一次遇到这类问题,所以也许我在考虑太多了。

    我对干净的解决方案感兴趣,这些解决方案不需要过多地实现其复杂性。也许我错过了WinAPI中优雅处理这个问题的东西?

    我还没有决定我会写什么,但我很满意:C,C ++,C#,D和Perl。

2 个答案:

答案 0 :(得分:1)

在评论中讨论后,我的建议就是这样:

  • 在数据服务器上创建一个分区,安全性约为5GB。
  • 在C#中创建一个用于监控数据驱动程序/位置的Windows服务项目。
  • 修改文件后,创建该文件的本地副本,其中包含相同的目录结构并放置在新分区上。
  • 创建另一项服务,执行以下操作:
    • 监控带宽使用情况
    • 监控临时分区上的文件创建。
    • 一次将多个文件(使用线程)传输到FTP服务器,遵守当前时间的带宽使用情况,根据网络流量减少/增加工作线程。
    • 从已成功传输的分区中删除文件。

所以基本上你有你的驱动器:

  • C: Windows安装
  • D:分享存储
  • X:临时分区

然后你会有以下服务:

  • LocalMirrorService - 观看D:并使用dir结构复制到X:
  • TransferClientService - 将文件从X:移至ftp服务器,从X:移除
    • 还可以使用多线程来移动倍数并监控带宽。

我敢打赌,这是你想到的想法,但这似乎是一种合理的方法,只要你的应用程序开发非常好,并且你能够创建一个可以处理大多数问题的可靠系统。

例如,当用户在Microsoft Word中编辑文档时,该文件将在共享上更改,并且可能会将其复制到X:,即使用户仍在使用它,在Windows中也会有API查看文件句柄是否仍由用户打开,如果是这种情况,那么您可以创建一个钩子,以便在用户实际关闭文档时进行监视,以便完成所有编辑,然后您可以迁移到驱动器{{1 }}

这就是说,如果用户正在处理文档并且由于某种原因PC崩溃,则文档/文件句柄可能不会在以后打开文档时释放,从而导致问题。

答案 1 :(得分:0)

对于处于类似情况的任何人(我假设很久以前问过该问题的人实施了解​​决方案),我建议实施rsync

rsync.net的Windows Backup Agent执行方法1中描述的操作,也可以作为服务运行(请参阅“Advanced Usage”)。虽然我不完全确定它是否内置带宽限制......

具有带宽限制的另一个(可能更好)解决方案是Duplicati。它还可以正确备份当前打开或锁定的文件。对其后端使用SharpRSync,一种托管的rsync实现。开源也是,这总是一个加号!