Erlang:创建filewatcher

Erlang:创建filewatcher,erlang,Erlang,我必须在Erlang中实现文件监视程序功能:应该有一个进程,在特定目录下列出文件,并在文件出现时执行某些操作 我看一下OTP。因此,目前我有以下想法: 1.创建将控制gen_服务器的主管(每个文件夹一台服务器) 2.为我要监视的每个文件夹创建WatchServer-gen_server。 3.创建ProcessFileServer-应该对文件执行某些操作的gen服务器)假定复制到不同的文件夹= 所以第一个问题是:WatchServer不应该等待请求,它应该在预定义的时间间隔内生成一个请求 目前,

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

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

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

目前,我已经在init/1函数中创建了一个计时器,并在handle\u info函数中创建了handle on\u timer事件

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


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

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

您可以尝试查看您的目录


Ulf

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

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

我建议采用以下结构:

                              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
当一个
目录观察者
注意到一个新文件出现时。它调用
processing\u supervisor
s
supervisor:start\u child\2
函数,并使用文件路径的额外参数,例如

处理\u主管
应使用
瞬态
重新启动策略启动其子级

因此,如果某个
proc_文件
服务器崩溃,它将重新启动,但当它们以退出原因
normal
终止时,它们不会重新启动。所以,当完成时,您只需退出
normal
,然后在发生其他任何情况时崩溃

如果您没有做得太多,循环轮询文件是可以的。如果系统由于这种轮询而被加载,您可以在内核通知系统(例如FreeBSD KQUEUE或MacOSX上基于它构建的更高级别服务)中进行调查,以便在目录中出现文件时向您发送消息。然而,这些服务有一个复杂性,因为如果发生太多事件,它们就有必要举手(否则它们不会是性能改进,相反)。因此,无论如何,您都必须有一个健壮的轮询解决方案作为后备方案

因此,不要过早地进行优化,从轮询开始,在必要时添加改进(这将在
dir\u watcher
服务器中隔离)


关于作为
dir\u watcher
进程使用什么行为的评论,因为它没有使用太多的
gen\u服务器
功能:

  • 只使用部分
    gen_服务器
    posibility是没有问题的,事实上,不使用所有服务器是很常见的。在您的情况下,您只需在
    init
    中设置一个计时器,并使用
    handle\u info
    来完成您的工作。gen_服务器的其余部分只是未更改的模板

  • 如果您以后想要更改参数,如轮询频率,可以很容易地添加到该参数中

  • gen_fsm
    使用较少,因为它只适用于非常有限的型号,而且不太灵活。我只在它真正100%符合要求时才使用它(它几乎从来没有这样做过)

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

  • 编写更自然的Erlang代码并且仍然具有OTP优势的一种有趣的方法是,这里您具有选择性接收和所需的灵活消息处理的优势,特别是当处理协议与OTP的良好特性相结合时


说了这么多:如果我要写一个
dir\u watcher
,我只会使用
gen\u服务器
,只使用我需要的东西。未使用的功能实际上不会花费您任何费用,每个人都了解它的用途。

我基于轮询编写了这样一个库。(如果能将其扩展到支持inotify的平台上,那就太好了。)它本来打算在EUnit中使用,但后来我变成了一个单独的项目。你可以在这里找到它:


这是一种优化,首先需要一个健壮的轮询解决方案。它完全依赖于操作系统(在Linux、FreeBSD和MacOSX上的实现方式有所不同——不知道Windows是否支持这一点)。虽然文件系统通知队列的系统负载比轮询更可取,但所有sane内核系统都有可能出现这些队列溢出的情况(否则,当创建大量小文件时,它们会使系统陷入困境)。这不是关于谁在Erlang中干净地实现这个问题的答案。我相信这个答案背后的想法是正确的,编写一个
端口
程序,它使用一个本地实现来正确可靠地实现这一点
inotify
在linux上,OSX上的
fsevents
和Windows上的等效系统库。不幸的是,我在Windows下,为了让生活更艰难,文件在网络共享上。据我所知,无法在网络共享上获取windows下的事件。事实上,我更喜欢平台无关的解决方案:)因为你看起来很新,所以:避免“你好”和“谢谢”这被认为是杂乱无章的,看我已经解决了你的问题。好的。有3个主管,看起来不是太复杂了吗?dir_watcher是否应该作为gen_服务器实现,或者