码迷,mamicode.com
首页 > 其他好文 > 详细

Erlang:RabbitMQ源码分析 4. file_handle_cache实现分析

时间:2014-09-14 11:24:57      阅读:196      评论:0      收藏:0      [点我收藏+]

标签:des   style   io   os   使用   ar   文件   div   sp   

RabbitMQ的文件操作使用file_handle_cache,将Erlang的prim_file Module包了一层。增加了writeBuffer和对文件打开数量的控制逻辑

file_handle_cache也是一个gen_server2,但一般来说只有Open操作会send message to gen_server2, 读写操作,包括writeBuffer都在Client Process里执行和维护。


file_handle_cache里存储了几张表:

   1. Elders:    {Pid, EldestUnusedSince},  存储每个client的pid 和其最老的Handle打开时间, 没有key

   2. Clients:   #cstate,存储每个client的信息,key是pid



下面我们从四个最基本的文件操作函数看一下file_handle_cache的实现:

open:

    1. file_handle_cache对于同一个文件是共享读但不共享写的,所以在client的Process Dictionary里存储了<key = {Path, fhc_file}, value = #file{ reader_count, has_writer}>,当open时如果发现has_writer = TRUE, open的model又是write,就直接返回{error, writer_exists};

    2. 新建一个closed的Handle,Handle相关的信息存储在client的Process Dictionary里 <key = {Ref, fhc_handle}, value = #handle>

    3. file_handle_cache在client的Process Dictionary里存储里一个gb_tree,用来保存这个client打开的所有Handle的打开时间。这个时间是用来调整Client Open的Handle个数。

    1-3都是在client的Process里做的

    4. gen_server:call open,  进入到file_handle_cache的Process loop里 , 当发现file_handle_cache打开的文件数不超过用户预设的文件数时,就update Clients table 和State,返回 OK。

    5. 回到client Process里,调用prim_file:open打开文件,所以打开文件的操作实际上市在Client Process里做的。

    6. 如果4中发现file_handle_cache打开的文件数超过用户预设的文件数时,

        6.1 如果这个pid已经打开了很多文件,就返回close, client接到close后就soft_close所有之前打开的Handle,所谓软关闭,就是将Handle对应文件buffer写完,sync后再关闭。软关闭所有之前打开的Handle后再重新试图open 这个Handle。

        6.2 如果这个pid没有打开任何文件,就对其他的pid下手,计算每个pid的最老时间(最早的打开的文件时间),累加算平均值。

             一般来说client在打开文件前会call register_callback 注册一个清理函数

             6.2.1 如果平均值大于两秒,说明有很多老文件还未关闭, 就对每个client call 清理函数。参数是最老时间的平均值。如果没有注册清理函数就不管。

             6.2.1 如果平均值小于两秒,说明没有很多未关闭的老文件。找到所有注册清理函数的pid, 假设有N个Open被Block,就用其中N个清理函数去清理N个已打开的Handle


close:

      1. 删掉ProcessDictionary 里的{Ref, fhc_handle}

      2. Handle的writebuffer 要prim_file:write

      3. 如果之前有write没有sync,call prim_file:sync

      4. call prim_file:close

      5. 将这个Handle的时间从gb_tree里删掉

      6. 更新Process Dictionary里的{Path, fhc_file}, read_count, write_count之类


read:  read本身没有什么特殊的,也没有用buffer

      1.  虽然已经Open过,但有可能因为打开文件过多被close,所以还是看下,如果被close了要reopen一下

      2.  Handle的writebuffer要prim_file:write

      3.  调用prim_file:read得到结果


append:

      1.  和read一样,也是有可能会reopen。

      2.  如果client在Open时没有设置WriteBuffer,就直接call prim_file:write(Hdl, Data)了事

      3.  所谓的Writebuff是针对于单个Handle的,即Open时搞一个空的List来做Buffer,append时如果BufferSize > Client Open时设置的limit,就call prim_file:write把Buffer都写到file里,如果BufferSize < limit,就只是将Data放到Buffer里即返回。




Erlang:RabbitMQ源码分析 4. file_handle_cache实现分析

标签:des   style   io   os   使用   ar   文件   div   sp   

原文地址:http://blog.csdn.net/liaosongbo/article/details/39210735

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!