`

[笔记]erlang gen_event使用

 
阅读更多

gen_event行为模式规定了怎么处理日志事件

该行为模式和gen_server不同 一个gen_server的实现只能绑定一个回调模块

而gen_event则可以回调多个模块 这个和在java中注册成为一个事件的监听者道理是一样的

一个日志事件(event)会分发给多个注册了的处理者(handler,gen_event行为模式的实现模块)

 

gen_event由start_link/0或/1进行初始化

一般使用start_link/1(可以使用start 用start_linik是为了和监督者连接起来)

start_link(EventMgrName) -> Result

Types:

EventMgrName = {local,Name} | {global,GlobalName} | {via,Module,ViaName}
Name = atom()
GlobalName = ViaName = term()
Result = {ok,Pid} | {error,{already_started,Pid}}
Pid = pid()

 使用的时候用诸如:

gen_event:start_link({local, ?SERVER}).

 的形式,注册一个名字叫?SERVER的本地事件管理器(以后的notify call等函数都要通过这个?SERVER来使用 (当然也可以使用返回的pid)

 

 

要增加一个handler用:

add_handler(EventMgrRef, Handler, Args) -> Result

Types:

EventMgr = Name | {Name,Node} | {global,GlobalName} | {via,Module,ViaName} | pid()
Name = Node = atom()
GlobalName = ViaName = term()
Handler = Module | {Module,Id}
Module = atom()
Id = term()
Args = term()
Result = ok | {'EXIT',Reason} | term()
Reason = term()

 这个就是为?SERVER(或者表示事件管理器的pid)命令的事件管理器增加一个 handler 

 handler就是实现了gen_event行为模式的模块的模块名

那么对应的反操作删除就是 参数一致。

delete_handler(EventMgrRef, Handler, Args) -> Result

Types:

EventMgrRef = Name | {Name,Node} | {global,GlobalName} | {via,Module,ViaName} | pid()
Name = Node = atom()
GlobalName = ViaName = term()
Handler = Module | {Module,Id}
Module = atom()
Id = term()
Args = term()
Result = term() | {error,module_not_found} | {'EXIT',Reason}
Reason = term()

 

接下去是函数的调用和对应模块(实现了gen_event行为模式的模块)内的回调的对应

gen_event:notify/2 gen_event:sync_notify/2----> module:handle_event/2

gen_event:call/3,4                                       ---->module:handle_call/2

module:handle_info/2用来接收没有定义的event(没有一个和module:handle_event匹配的)或者系统消息

 

一般使用gen_event:notify/2就足够了,其他的在doc里有详细解释

以下是一个例子:

这个例子来自erlang/OTP并发编程实战 是一个完整的小程序 我这边把日志模块单独抽取了出来

完整的程序代码见:

https://github.com/erlware/Erlang-and-OTP-in-Action-Source/tree/master/chapter_07/simple_cache

 

首先是产生事件源的代码:

-module(sc_event).

-export([start_link/0,
         add_handler/2,
         delete_handler/2,
         lookup/1,
         create/2,
         replace/2,
         delete/1]).

-define(SERVER, ?MODULE).

start_link() ->
    gen_event:start_link({local, ?SERVER}).

add_handler(Handler, Args) ->
    gen_event:add_handler(?SERVER, Handler, Args).

delete_handler(Handler, Args) ->
    gen_event:delete_handler(?SERVER, Handler, Args).

lookup(Key) ->
    gen_event:notify(?SERVER, {lookup, Key}).

create(Key, Value) ->
    gen_event:notify(?SERVER, {create, {Key, Value}}).

replace(Key, Value) ->
    gen_event:notify(?SERVER, {replace, {Key, Value}}).

delete(Key) ->
    gen_event:notify(?SERVER, {delete, Key}).

 这段代码不难理解  模块名是sc_event 里面封装了gen_event的调用

 gen_event初始化时注册了 和模块同名的本地事件管理器 然后接下去的notify方法调用的第一个参数就是这个管理器的名字

通过add_handler和delete_handler对处理模块进行移入和移出操作

 

接下去的代码是自定义的日志处理(handler) 实现了gen_event行为模式:

-module(sc_event_logger).

-behaviour(gen_event).

-export([add_handler/0, delete_handler/0]).

-export([init/1, handle_event/2, handle_call/2,
         handle_info/2, code_change/3, terminate/2]).

-record(state, {}).

add_handler() ->
    sc_event:add_handler(?MODULE, []).

delete_handler() ->
    sc_event:delete_handler(?MODULE, []).

init([]) ->
    {ok, #state{}}.

handle_event({create, {Key, Value}}, State) ->
    error_logger:info_msg("sc_event_logger:create(~w, ~w)~n", [Key, Value]),
    {ok, State};
handle_event({lookup, Key}, State) ->
    error_logger:info_msg("sc_event_logger:lookup(~w)~n", [Key]),
    {ok, State};
handle_event({delete, Key}, State) ->
    error_logger:info_msg("sc_event_logger:delete(~w)~n", [Key]),
    {ok, State};
handle_event({replace, {Key, Value}}, State) ->
    error_logger:info_msg("sc_event_logger:replace(~w, ~w)~n", [Key, Value]),
    {ok, State}.

handle_call(_Request, State) ->
    Reply = ok,
    {ok, Reply, State}.

handle_info(_Info, State) ->
    {ok, State}.

terminate(_Reason, _State) ->
    ok.

code_change(_OldVsn, State, _Extra) ->
    {ok, State}.

 这边也比较好理解 各个handle_event用来处理事件源中发出的不同事件

 

单独调用如下:

1> c(sc_event).
{ok,sc_event}
2> c(sc_event_logger).
{ok,sc_event_logger}
3> sc_event:start_link().
{ok,<0.45.0>}
4> sc_event_logger:add_handler().
ok
5> sc_event:lookup("test").
ok
6>
=INFO REPORT==== 14-Jul-2013::11:04:38 ===
sc_event_logger:lookup([116,101,115,116])

 

分享到:
评论

相关推荐

    erlang-gen_tcp手册

    erlang-gen_tcp手册,详细完整,网络tcp开发好东东

    基于Erlang的gen_tcp聊天室代码,功能完整

    在这个场景中,我们讨论的是一个使用Erlang和gen_tcp编写的聊天室应用。 **gen_tcp简介** gen_tcp是Erlang OTP(开放电信平台)提供的一种行为模块,它允许程序员以面向过程的方式处理TCP连接。gen_tcp提供了创建、...

    erLang otp_win64_20.2安装包

    Erlang opt_win64 20.2 windows exe 安装包 Erlang 20.2 is the upcoming version of Erlang For Windows x64 installer 截至2018.01.25 groovy最新最稳定版本

    esl-erlang_23.0_windows_amd64.exe rabbitmq-server-3.8.4.exe

    esl-erlang_23.0和rabbitmq-3.8.4windows版本 直接下载安装就行,可以直接下载就可安装,非常的方便 ,欢迎大家下载 注意事项: 1. Erlang版本和RabbitMQ版本要配套 (Erlang23.0, RabbitMQ3.8.4) 2. amd芯片请乖乖...

    Erlang_B_model.rar_Erlang B _Erlang B model_Wireless Handbook_e

    在这个压缩包中,我们有一个名为"Erlang_B_model.pdf"的文件,它很可能是这样的手册的一部分,提供了关于Erlang B模型的理论、公式以及查表方法。 **Erlang B公式**表达了一个服务系统(如电话交换机)在固定数量的...

    gen_server tasting 之超简单名称服务(续)

    在IT行业中,`gen_server`是Erlang OTP(开放电信平台)框架中的一个核心组件,它提供了一种模式化的方式来实现服务器进程。本篇博客“gen_server tasting 之超简单名称服务(续)”主要探讨了如何使用gen_server来...

    gen_server:Erlang 的 gen_server 的(不完整的)OcamlAsync 实现

    《Erlang gen_server在OcamlAsync中的实现探索》 Erlang的gen_server是其并发模型的核心组件,它提供了一种强大的状态管理和错误处理机制。而在OCaml语言中,尽管有着自己的并发库如Async,但直接移植或模仿Erlang...

    gen_tcp_server:Erlang 应用程序的通用 TCP 服务器

    通用 TCP 服务器 通用 TCP 服务器( gen_tcp_server ) 是一种 Erlang 行为,提供快速简便的方法将 TCP 服务器功能添加到您的应用程序。 它被实现为管理 TCP 连接的主管,因为它是孩子。如何使用它? 运行make来构建。...

    Erlang otp_src_20.3.tar.gz

    安装完成后,你就可以使用新编译的Erlang OTP 20.3执行你的应用程序,或者开始开发基于Erlang的系统。同时,由于其与RabbitMQ的兼容性,你可以创建和管理RabbitMQ集群,利用其强大的消息传递能力。 总之,Erlang ...

    erlang otp_src_20.2.tar.gz

    3. **安装到系统**:编译成功后,使用`sudo make install`命令将Erlang OTP安装到系统路径,一般为/usr/local/。为了防止权限问题,可能需要使用管理员权限。 4. **验证安装**:安装完成后,通过运行`erl`命令启动...

    erlang tcp_server

    4. **gen_tcp模块**:这个模块提供了处理TCP连接的函数,如`gen_tcp:connect/3`用于建立客户端连接,`gen_tcp:recv/2,3`用于接收数据,`gen_tcp:send/2`用于发送数据,以及`gen_tcp:close/1`用于关闭连接。...

    esl-erlang_23.0_windows_amd64.exe

    这个erlang23.0版本,根据rabbitMQ官网的介绍,可以和下面这几个版本的rabbitMQ配合使用: 3.8.9 3.8.8 3.8.7 3.8.6 3.8.5 3.8.4 其他版本的rabbit,请移步其他资源下载

    Erlang-Formula.zip_Erlang B _Erlang-B_erlang_erlang B计算_erlang C

    Erlang B 和 Erlang C 是在电信领域中广泛使用的两个数学公式,用于预测和管理电话交换系统的呼叫处理能力。这两个公式由丹麦工程师 Agner Krarup Erlang 在20世纪初开发,对于理解通信系统中的呼叫占用率、阻塞率和...

    erlang_otp_src_22.3.tar.gz

    首先,Erlang 语言以其独特的并发模型闻名,它使用轻量级进程(Lightweight Processes,LWP)来实现并发执行。这些进程具有低开销,使得在单个硬件上可以同时运行成千上万个进程。这使得 Erlang 在处理大规模并发...

    Erlang_OTP_设计原理(含目录).pdf

    行为(Behavior)是一组预定义的模式,用于实现常见类型的进程,如服务器进程(Gen_Server)、有限状态机(Gen_Fsm)、事件处理器(Gen_Event)和监督进程(Supervisor)。这些行为模式通过行为模块和回调模块的分离...

    erlang_otp_win64_20.3.zip

    是erlang_otp_20.3 的win64安装包,内为exe文件,一路next即可安装完成 是适用于多线程、分布式开发的语言,也是如rabbitmq等重要工具的必须品 使用前需要配置环境变量:1.变量名为ERLANG_HOME,变量值为安装Erlang...

    megaco_session-0.5.rar_erlang_erlang Megaco_megaco

    “erlang_erlang_megaco”标签进一步强调了这个项目与Erlang语言以及Megaco协议的关联。Megaco(也称为H.248)是一种通信协议,主要用于在多媒体网关控制器(MGC)和多媒体网关(MG)之间进行交互,以控制VoIP...

    Erlang otp_win64_20.1.exe

    Erlang otp_win64_20.1.exe是当前最新版本的,更新时间2017-10-26

    esl-erlang_23.0.2-1_centos_7_amd64.rpm

    erlang_23.0.2-1版本 centos7 64bit esl-erlang_23.0.2-1_centos_7_amd64.rpm

    gen_tcp的close与delay_send交叉问题

    可以使用`gen_tcp:flush/1`来发送所有待发送的数据,或者在关闭连接之前检查`delay_send`的状态。如果`delay_send`是启用的,可以暂时禁用它,发送完所有数据后再恢复。 此外,了解Erlang的进程模型也很重要,因为...

Global site tag (gtag.js) - Google Analytics