Erlang:创建filewatcher

时间:2011-04-15 20:40:35

标签: erlang

我必须在Erlang中实现文件监视器功能:应该有一个进程列出文件,如果是特定目录,并在文件出现时执行某些操作。

我看看OTP。所以目前我有以下想法: 1.创建将控制gen_servers的Supervisor(每个文件夹一个服务器) 2.为我要监视的每个文件夹创建WatchServer - gen_server。 3.创建ProcessFileServer - 应该对文件执行某些操作的gen服务器)假设复制到不同的文件夹=

所以第一个问题:WatchServer不应该等待请求,它应该以预定义的间隔生成一个。

目前我已在init / 1函数中创建了一个计时器,并在handle_info函数中处理on_timer事件。

现在问题: 1.有更好的想法吗? 2.如何通知ProcessFileServer找到的文件?它对我来说,独立创建WatchServers和ProcessServers会更方便,但在这种情况下我不知道向谁发送消息?

可能有一些类似的项目/库可用吗?

3 个答案:

答案 0 :(得分:4)

如果您使用的是Linux,则可以使用inotify。它是一个内核服务,允许您订阅文件系统事件。不要轮询文件系统,让文件系统给你打电话。

您可以尝试https://github.com/massemanet/inotify来观察您的目录。

乌尔夫

答案 1 :(得分:2)

在Erlang中,创建流程(与其他系统相比的数量级)非常便宜。

因此,我建议每次出现要处理的新文件时都创建一个新的ProcessFileServer。完成后,只需使用退出原因normal终止流程。

我建议采用以下结构:

                              top_supervisor
                                      |
              +-----------------------+-------------------------+
              |                                                 |
       directory_supervisor                             processing_supervisor
               |                                         simple_one_for_one
    +----------+-----...-----+                                   |
    |          |             |                       starts children transient
    |          |             |                                   |
dir_watcher_1 dir_watcher_2 dir_watcher_n   +-------------+------+---...----+
                                            |             |                 |
                                        proc_file_1   proc_file_2       proc_file_n

dir_watcher注意到新文件出现时。它使用文件的额外参数调用processing_supervisor s supervisor:start_child\2函数,例如。

processing_supervisor应该使用transient重新启动政策启动其子级。

因此,如果其中一个proc_file服务器崩溃,它将重新启动,但当它们以退出原因normal终止时,它们不会重新启动。所以你完成后就退出normal,当发生其他事情时崩溃。

如果你没有过头,那么文件的循环轮询就可以了。如果由于此轮询而导致系统加载,您可以在内核通知系统(例如FreeBSD KQUEUE或MacOSX上构建的更高级别服务)上进行调查,以便在文件出现在目录中时向您发送消息。然而,这些服务具有复杂性,因为如果发生太多事件,他们必须举手(否则他们不会提高性能,反之亦然)。所以你必须有一个强大的轮询解决方案作为后备。

因此,不要进行过早优化并从轮询开始,在必要时添加改进(将在dir_watcher服务器中隔离)。


关于评论用作dir_watcher进程的行为,因为它没有使用gen_servers个大部分功能:

  • 仅使用部分gen_servers可能性没有问题,事实上不使用全部内容是很常见的。在您的情况下,您只需在init中设置一个计时器,然后使用handle_info来完成您的工作。 gen_server的其余部分只是未更改的模板。

  • 如果您以后想要更改轮询频率等参数,则很容易添加到此。

  • gen_fsm使用率较低,因为它只适用于非常有限的模型而且不够灵活。我只在它真正符合要求的情况下使用它(几乎从不这样做)。

  • 如果您只想要一个简单的普通Erlang服务器,可以使用proc_lib中的spawn函数来获得在主管下运行的最小功能。

  • 编写更自然的Erlang代码并且仍具有OTP优势的一种有趣的方法是plain_fsm,这里有选择性接收和灵活的消息处理所需的优势,尤其是在处理与良好功能配对的协议时OTP。

说完这一切:如果我写一个dir_watcher,我只需要使用gen_server并仅使用我需要的东西。未使用的功能并没有真正花费你任何东西,每个人都知道它的作用。

答案 2 :(得分:2)

我根据民意调查编写了这样一个图书馆。 (将它扩展为在支持它的平台上使用inotify会很好。)它原本打算用于EUnit,但我转而成为一个单独的项目。你可以在这里找到它:

https://github.com/richcarl/file_monitor