mochiweb 源码阅读(九)
2012-07-24 10:06 rhinovirus 阅读(1636) 评论(5) 编辑 收藏 举报今天还是一样,要去驾校练车,早起不用上班,看看mochiweb源码,继续和大家分享。昨天有个函数给跳过了,今天看了下,也有不少知识点,还是补下吧,函数:mochiweb_socket_server:parse_options/1,完整代码如下:
parse_options(State=#mochiweb_socket_server{}) -> State; parse_options(Options) -> parse_options(Options, #mochiweb_socket_server{}).
如果传递的是配置是#mochiweb_socket_server{}记录类型,则直接返回,否则调用mochiweb_socket_server:parse_options/2,传递配置列表,以及#mochiweb_socket_server{},这里Options的值为:
< Options = [{loop,{mochiweb_http,loop,
[#Fun<mochiweb_example_web.0.8815963>]}},
{name,mochiweb_example_web},
{ip,{0,0,0,0}},
{port,8080}]
我们来逐个分支分析下:
分支一(配置列表为[]的处理):
parse_options([], State) ->
State;
如果配置项为[],返回State;
分支二(关于name部分的处理):
parse_options([{name, L} | Rest], State) when is_list(L) -> Name = {local, list_to_atom(L)}, parse_options(Rest, State#mochiweb_socket_server{name=Name}); parse_options([{name, A} | Rest], State) when A =:= undefined -> parse_options(Rest, State#mochiweb_socket_server{name=A}); parse_options([{name, A} | Rest], State) when is_atom(A) -> Name = {local, A}, parse_options(Rest, State#mochiweb_socket_server{name=Name}); parse_options([{name, Name} | Rest], State) -> parse_options(Rest, State#mochiweb_socket_server{name=Name});
这四个分支是跟{name, ?}相关的,当?分别为:list,undefined,atom,其他值,这四种情况分别调用这四个分支其中一个,我们看下这里用到了哪些系统函数:
函数:is_list/1,erlang doc 地址:http://www.erlang.org/doc/man/erlang.html#is_list-1,如下图:
如果Term是一个零个或多个元素的列表返回true,否则返回false。
函数:list_to_atom/1,erlang doc 地址:http://www.erlang.org/doc/man/erlang.html#list_to_atom-1,如下图:
返回字符串的文本表示原子。
注意:这里其实是不严谨的,虽然字符串是特殊的列表,但是如果传递[a, b,c]这样的列表,它是满足is_list/1为true的,但是调用list_to_atom/1却会抛出异常的。
函数:is_atom/1,erlang doc 地址:http://www.erlang.org/doc/man/erlang.html#is_atom-1,如下图:
如果Term是一个原子,返回true,否则返回false。
我在shell做了些测试例子,如下图:
注意抛异常的部分。关于分支二,剩下就是修改记录中name字段的值了,很简单,我们继续往下看。
分支三(关于port部分的处理):
parse_options([{port, L} | Rest], State) when is_list(L) -> Port = list_to_integer(L), parse_options(Rest, State#mochiweb_socket_server{port=Port}); parse_options([{port, Port} | Rest], State) -> parse_options(Rest, State#mochiweb_socket_server{port=Port});
这里先看下系统函数:list_to_integer/1,erlang doc 地址:http://www.erlang.org/doc/man/erlang.html#list_to_integer-1,如下图:
根据字符串的文本返回返回一个整数。失败:如果字符串包含不是数字的文本,则会提示badarg。
测试如下:
剩下就是修改记录中port字段的值;
分支四(ip部分的处理):
parse_options([{ip, Ip} | Rest], State) -> ParsedIp = case Ip of any -> any; Ip when is_tuple(Ip) -> Ip; Ip when is_list(Ip) -> {ok, IpTuple} = inet_parse:address(Ip), IpTuple end, parse_options(Rest, State#mochiweb_socket_server{ip=ParsedIp});
看下系统函数:is_tuple/1,erlang doc 地址:http://www.erlang.org/doc/man/erlang.html#is_tuple-1,如下图:
如果Term为元组类型,则返回true,否则返回false。
系统函数:inet_parse:address/1,erlang doc 地址:http://www.erlang.org/doc/man/inet.html,这个模块我没找到,只在上面那个地址看到部分例子,如下图:
大概就是把一个字符串格式的ip地址,转为{ok, {192,168,1,1}}类似这样的格式。
测试例子如下:
剩下就是和之前没什么区别,修改对应记录中字段的值,这里是ip字段。
分支五:
parse_options([{loop, Loop} | Rest], State) -> parse_options(Rest, State#mochiweb_socket_server{loop=Loop}); parse_options([{backlog, Backlog} | Rest], State) -> parse_options(Rest, State#mochiweb_socket_server{backlog=Backlog}); parse_options([{nodelay, NoDelay} | Rest], State) -> parse_options(Rest, State#mochiweb_socket_server{nodelay=NoDelay});
这部分分支,直接就是修改对应记录中字段的值,很简单,我们直接跳过。
分支六:
parse_options([{acceptor_pool_size, Max} | Rest], State) -> MaxInt = ensure_int(Max), parse_options(Rest, State#mochiweb_socket_server{acceptor_pool_size=MaxInt});
这里首先调用函数 mochiweb_socket_server:ensure_int/1:
ensure_int(N) when is_integer(N) -> N; ensure_int(S) when is_list(S) -> list_to_integer(S).
很简单,如果是数字类型,则直接返回,如果是文本为数字的字符串,则转为数字后返回。
由于剩下分支逻辑都比较简单,我把剩余分支都贴出来,只讲不同的部分:
parse_options([{max, Max} | Rest], State) -> error_logger:info_report([{warning, "TODO: max is currently unsupported"}, {max, Max}]), MaxInt = ensure_int(Max), parse_options(Rest, State#mochiweb_socket_server{max=MaxInt}); parse_options([{ssl, Ssl} | Rest], State) when is_boolean(Ssl) -> parse_options(Rest, State#mochiweb_socket_server{ssl=Ssl}); parse_options([{ssl_opts, SslOpts} | Rest], State) when is_list(SslOpts) -> SslOpts1 = [{ssl_imp, new} | proplists:delete(ssl_imp, SslOpts)], parse_options(Rest, State#mochiweb_socket_server{ssl_opts=SslOpts1}); parse_options([{profile_fun, ProfileFun} | Rest], State) when is_function(ProfileFun) -> parse_options(Rest, State#mochiweb_socket_server{profile_fun=ProfileFun}).
首先是:error_logger:info_report/1,erlang doc 地址:http://www.erlang.org/doc/man/error_logger.html#info_report-1,如下图:
发送一个标准信息报告事件的错误记录。事件处理的标准事件处理程序。其实就是使用sasl往shell显示事件信息。
函数:is_boolean/1,is_function/1,和之前讲过的is_list/1是一个意思,判断是否是对应的数据类型,一通百通,也不重复说了。
好了,这一篇,就到这里。谢谢大家的耐心阅读,咱们下一篇再见。
本文基于署名-非商业性使用 3.0许可协议发布,欢迎转载,演绎,但是必须保留本文的署名rhinovirus(包含链接http://www.cnblogs.com/rhinovirus/),且不得用于商业目的。如您有任何疑问或者授权方面的协商,请与我联系。