local pid and remote pid

pid 既可以代表本地的process,也可以代表其他节点即远程 process,因此pid ! Msg,既可以向本地节点又可以向其他节点发送消息。
如何来区分local pid和remote pid呢,让我们先看看pid具体包含哪些信息。
打印pid变量的时候,其为X.Y.Z格式的数据,其中X代表的便是本地节点或者其他node(其可以为一个索引,指向某个已知节点),Y为4字节unsigned integer代表的是process id(序列号),Z为1个字节,用来标识节点的新旧(如果节点发生了crash,那么这个数值就会发生变化,通常为0)。
具体的pid数据格式请参考:http://www.erlang.org/doc/apps/erts/erl_ext_dist.html#8.8
在分布式开发中,如果节点之间交互,涉及到pid,那么erlang会自动为我们进行local pid到remote pid的转化。具体请参看下例:
为了方便我们的观察,研究,我对kernel中的rpc模块作了一点小改动,添加了一些调试信息:
rpc.erl:
handle_call/3函数 Line 99添加:

io:format(”rpc handle_call:[M:~p F:~p A:~p] From:~p~n”, [Mod, Fun, Args, To]),

handle_info/2函数 Line 148添加:

io:format(”rpc reply To: ~p Msg:~p~n”, [To, Reply]),

do_call/3函数 Line 232

io:format(”rpc docall: Node:~p self:~p~n”, [Node, self()]),

添加完这三条打印信息,随后编译rpc,将rpc.beam放置在kernerl/ebin目录下。(修改前,相信你会把rpc.erl和rpc.beam都备份一下的)。
随后我们启动两个erlang shell:

Node A: erl -sname a
Node B: erl -sname b

在Node b中,我们register一个名叫proc_on_b的process:

(b@desktop)4> register(proc_on_b, spawn(fun() -> receive Msg -> Msg end end)).

在Node [...]

Erlang不能错过的盛宴

昨天写了一个简单的文档,为想学习Erlang的朋友,提供一点点的资料。
书写仓促,纰漏难免。望各位朋友不吝指正。
下载地址:
下载地址1
下载地址2

Erlang China 大会 - CN Erlounge III - 发起

详细信息参阅: http://ecug.org/
欢迎大家四处传播此消息。
————————-
正在传播!

erlang项目开发之-dialyzer和eunit

这个东西如果写,可能会写很长很长的篇幅,但是有悖erlang的精神,
我就挑选最精要的说,也是自己这几天学习到的一些东西。
一个项目,首先设计完成后,日夜赶工,写成了代码。这个时候,我们就要检验代码是否真实的表达了我们的意图。
dialyzer和eunit就派上用场了!
dialyzer偏向于static“静态”的代码分析,其主要完成以下工作:
1,可能出现的拼写错误
2,没有使用的代码和函数
3,无用的测试代码
如果想让dialyzer更高效出色的工作,就需要代码中的type(类型)和spec(函数)进行配合。
我们知道erlang是动态的语言,本身没有很多静态的信息,我们就是通过这些-type和-spec来规范代码的静态性。
具体的type和spec的说明,请参考:http://www.erlang.org/eeps/eep-0008.html
说明几点:type通常我们定义在一个hrl文件中,需要这个type信息的erl文件,只要include此头文件既可。每个module的所有的export函数都应该有spec信息.
验证了静态信息,我们还需要通过eunit测试我们的逻辑是否正确.当然这里只是单元测试.每次我们修改完代码以后,我们都可以重新进行单元测试,验证我们的模块,大大节省时间.
eunit文档:
http://svn.process-one.net/contribs/trunk/eunit/doc/overview-summary.html
dialyzer和eunit进行完以后,那么就集成测试了.最后期待能制作一个坚固的产品!

erlkad-erlang kademlia dht library

http://code.google.com/p/erlkad/
闲暇无事,就用erlang写了一个kad libarary。
放到google code上,最近刚做完单元测试,还需要进一步的测试。
还有一点就是没有做好release,回头准备用erlware的系列工具来生成安装包。
回头会写一些开发过程中的心得。 :)

erlang lru cache module

1个月前写ecrawler的时候,需要一个lru cache算法。
erlang中好像没有特别合适的选择,就自己实现了一个。
思想:
采用gb_trees保存key-value pair,可以实现快速的key lookup,但是当发生替换时,
需要根据访问时间清理item,我们可能需要gb_trees中的数据导入到list中,随后进行排序,然后调换掉比较旧的内容。为了改善性能,我将数据在list中做一个拷贝,但是注意不包含value,只是key和一些状态信息。
当发生替换时,我们可以直接对list进行排序(也可以在每次操作的时候,将item插入到list中的合适位置,保持list有序),随后删除最旧的元素。
采用此方法比gb_trees:to_list方法效率稍高。当然没有做太多的性能测试,比如gb_trees用dict, ets替换等,我们的原则还是,先让代码正确,随后再让代码高效。
接口:
new/1, get/2, insert/3, insert/4, size/1, max/1, hitrate/1, to_list/1
废话不说了,看代码吧,写的不足之处请见谅。
下载代码

erlang gen_server牛角尖问答

我们以Module代表gen_server的callback模块
1, 实现gen_server behaviour的模块会产生一个新的process么?
毫无疑问,太会了!通过调用proc_lib:start_link/5创建process
2, gen_server:start_link/3,4中的Options参数有什么用处?
Options中只有这几个选项:{debug,Dbgs} | {timeout,Time} | {spawn_opt,SOpts},
debug是用来和sys模块相关联的;咱们通过proc_lib:start_link/5创建process的时候,如果初始化等待的时间超过了Time,那么我们的gen_server:start_link会返回{error, timeout}的错误;spawn_opt是给spawn_opt传递的参数。
3, Module:init/1的那些返回值都什么意思?
{ok, State},就不用说了,一切正常,State将为gen_server的State;
{ok, State, Timeout},也很正常,只是如果process在Timeout(>=0,ms)时间内没有收到任何消息,那么将产生一个timeout消息,这个消息要在handle_info中处理哦。
{ok, State, hibernate}, 还是正常,只是我们在process启动后,就让它先”睡眠“,因为我们知道最近一段时间内,我们还不用这个process,此process睡眠的好处就是可以最大限度的减少其内存占用,当有消息到达时,process就会”惊醒“,重新工作。
{stop, Reason},oops,出错了,process将会调用exit(Reason)退出。如果init没有预期,我们就退出吧。
ingore,既然要求忽略了,什么都不做,退出吧。
4, gen_server:multi_call/2,3,4这几个哥们是干嘛用的?
multi就是多的意思嘛,mulit_call肯定就是进行多个调用请求哦。
先说他们的关系:
gen_server:multi_call(Name, Request)
= gen_server:multi_call([node() | nodes()], Name, Request)
= gen_server:multi_call([node() | nodes()], Name, Request, infinity)
称他们为兄弟,我看称他们为三胞胎还不错。
想多个node请求本地名为Name的gen_server behaviour, 然后收集结果,返回。
其返回值格式为:{Replies,BadNodes},其中Replies为[{Node, Reply}],BadNodes,不用说就是那些没有正常返回应答的节点了。
mulit_call/4最后一个Time参数指定的是每个Reply等待的超时时间。
5, gen_server:reply/2有嘛用处?
如果在Module:handle_call/3中,我们不能返回结果,我们可以保存handle_call中的From参数,在结果生成的时候,返回给Caller。
6, Module:handle_call/3 返回{noreply,NewState}会怎样?
怎样?明明是handle_call处理的是同步的请求,处理完了就应该告诉Caller,是死是活,是成功是失败,可是你noreply,
Caller只能傻傻的等待了。等多久?默认的是5秒,gen_server:call/3就调用exit({timeout, Description}),退出了。。
7, 我用gen_server竟然死锁了?
天呀,在erlang中怎么遇到锁了?肯定是你使用不当!

name() ->
gen_server:call(?SERVER, name).
address() ->
gen_server:call(?SERVER, address).

all_info() ->
gen_server:call(?SERVER, all_info).

…..
handle_call(all_info, _From, State) ->
Name = name(),
Address = address(),
{reply, {Name, Address}, [...]

couchdb剖析

很对不起这个题目,因为这个是转贴文章,我只是看了一部分,没有精力翻译。
感兴趣的朋友认真看一下吧:

from Ayende Rahien.
Reading Erlang: CouchDB - From REST to Disk in a few function calls
Erlang Reading: CouchDB - Digging Down to Disk
Reading Eralng: CouchDB Streams
Previous CouchDB articles by Ayende
Reading Erlang: Inspecting CouchDB
More CouchDB reading: btree:lookup
More CouchDB reading: btree:query_modify
等手头工作搞完了,一定认真的研究一下couchdb。
今天就说点“浅显”的东西,couchdb中使用mochiweb。
couchdb提供了HTTP API进行各种访问控制,灵活,方便,便于开发web应用。
其HTTP server基于mochiweb。
在couch_httpd.erl的start_link/3函数中:

Loop = fun (Req) -> apply(couch_httpd, handle_request, [Req, DocumentRoot]) end,
mochiweb_http:start([
[...]

国庆放假,今天就回家了。

国庆放假,今天我就要回家了。所以会有很长一段时间不能更新blog了。呵呵
但是中间会一直学习,进步的!
祝各位朋友节日快乐!注意安全!

Erlang vs Ruby

老外的形象比喻:
http://notdennisbyrne.blogspot.com/2008/06/ruby-and-erlang.html

Erlang

Ruby

并发

类型
函数式编程
面向对象

语法

用途
后台
前台