diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..16df7e1
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,9 @@
+*.o
+*.so
+*.so.*
+tags
+src/tsar
+*.DS_Store
+*.dSYM
+cscope.out
+ttsar.sh
diff --git a/ChangeLog b/ChangeLog
index e66d28e..5eaa8a6 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,13 @@
+2017-12-12
+* 支持Lua语言开发模块
+2015-12-14
+* 增加了tsar -w 功能
+2015-07-27
+* output_tcp 增加了多目的发送功能，目前最多支持4个地址，以空格隔开
+2013-03-06
+* tsar的模块支持参数配置
+2013-01-23
+* tsar支持--spec功能，可以指定特定字段来显示
 2013-01-16
 * merge inner and opensource tsar version
 2011-05-18
diff --git a/Makefile b/Makefile
index ed4e8f3..e14d8f0 100644
--- a/Makefile
+++ b/Makefile
@@ -1,4 +1,4 @@
-DIRS = modules src
+DIRS = src modules lualib
 
 all:
 	for i in $(DIRS); do make -C $$i; done
@@ -6,10 +6,11 @@ all:
 clean:
 	for i in $(DIRS); do cd $$i;make clean;cd ..; done
 
-install:
+install: all
 	#mkdir for tsar
 	mkdir -p /usr/local/tsar/modules
 	mkdir -p /etc/tsar
+	mkdir -p /usr/local/man/man8/
 	#copy tsar shared so
 	cp modules/*.so /usr/local/tsar/modules
 	#copy bin file
@@ -20,14 +21,8 @@ install:
 	cp conf/tsar.cron /etc/cron.d/tsar
 	#copy man file
 	cp conf/tsar.8 /usr/local/man/man8/
-
-tsardevel:
-	mkdir -p /usr/local/tsar/devel
-	cp devel/mod_test.c /usr/local/tsar/devel/mod_test.c
-	cp devel/mod_test.conf /usr/local/tsar/devel/mod_test.conf
-	cp devel/tsar.h /usr/local/tsar/devel/tsar.h
-	cp devel/Makefile.test /usr/local/tsar/devel/Makefile.test
-	cp devel/tsardevel /usr/bin/tsardevel
+	#install lualib
+	make -C lualib install
 
 uninstall:
 	#rm tsar
@@ -40,5 +35,30 @@ uninstall:
 	rm -f /usr/bin/tsar
 	#rm tsardevel
 	rm -f /usr/bin/tsardevel
+	#rm tsarluadevel
+	rm -f /usr/bin/tsarluadevel
 	#backup configure file
-	mv /etc/tsar/tsar.conf /etc/tsar/tsar.conf.rpmsave
+	if [ -f /etc/tsar/tsar.conf ]; then mv /etc/tsar/tsar.conf /etc/tsar/tsar.conf.rpmsave; fi
+	#backup the log data file
+	if [ -f /var/log/tsar.data ]; then mv /var/log/tsar.data /var/log/tsar.data.bak; fi
+
+tsardevel:
+	mkdir -p $(DESTDIR)/usr/local/tsar/devel
+	cp devel/mod_test.c $(DESTDIR)/usr/local/tsar/devel/mod_test.c
+	cp devel/mod_test.conf $(DESTDIR)/usr/local/tsar/devel/mod_test.conf
+	cp devel/tsar.h $(DESTDIR)/usr/local/tsar/devel/tsar.h
+	cp devel/Makefile.test $(DESTDIR)/usr/local/tsar/devel/Makefile.test
+	cp devel/tsardevel $(DESTDIR)/usr/bin/tsardevel
+
+tsarluadevel:
+	mkdir -p $(DESTDIR)/usr/local/tsar/luadevel
+	cp luadevel/mod_lua_test.lua $(DESTDIR)/usr/local/tsar/luadevel/mod_lua_test.lua
+	cp luadevel/mod_lua_test.conf $(DESTDIR)/usr/local/tsar/luadevel/mod_lua_test.conf
+	cp luadevel/Makefile.test $(DESTDIR)/usr/local/tsar/luadevel/Makefile.test
+	cp luadevel/tsarluadevel $(DESTDIR)/usr/bin/tsarluadevel
+
+tags:
+	ctags -R
+	cscope -Rbq
+
+.PHONY: all clean install unintall tsardevel tsarluadevel tags
diff --git a/README b/README
deleted file mode 100644
index 7868d94..0000000
--- a/README
+++ /dev/null
@@ -1,89 +0,0 @@
-* Introduce
-Tsar is Taobao monitor tool for collect system activity status, and report it. It have a plugin system that is easy for collect plugin development. and may setup different output target such as local logfile and remote nagios host.
-
-NAME
-       tsar - Taobao System Activity Reporter
-
-SYNOPSIS
-       tsar [options] --tsar main function
-
-       tsardevel [modname] --develop new mod
-
-DESCRIPTION
-       tsar is a monitor tool for collect system activity status and apps.
-
-       tsar  reads  and  logs  messages to the log files,It support different output target such as local console or remote db/nagios host.It
-       have a plugin system that is easy for collect plugin development.
-
-OPTIONS
-       -check , -check
-              display last record for alert,it is just used for taobao inner alert
-
-       -C , --check
-              display last record for alert.example:tsar --check / tsar --check --cpu --io
-
-       -c , --cron
-              run in cron mode, output data to file,default is /var/log/tsar.data
-
-       -l ,--live
-              running print live mode which module will print
-
-       -i , --interval
-              specify intervals numbers, if not with --live,it is in minutes;if with --live, it is in seconds
-
-       -m , --merge
-              merge multiply item to one
-
-       -L , --list
-              list enabled modules
-
-       -n , --ndays
-              show the value for the past days (default: 1)
-
-       -d , --date
-              special one day to display,support formate YYYYMMDD or int for somedays ago
-
-       -f , --file
-              special tsar.data for tsar to read
-
-       -n , --ndays
-              show the value for the past days (default: 1)
-
-       -d , --date
-              special one day to display,support formate YYYYMMDD or int for somedays ago
-
-       -f , --file
-              special tsar.data for tsar to read
-
-       -n , --ndays
-              show the value for the past days (default: 1)
-
-       -D ,--detail
-              do not conver data to K/M/G
-
-       -s ,--spec
-              show spec field data, tsar --cpu -s sys,util
-
-       -h , --help
-              print help info
-
-       DIAGNOSTICS
-              It is expected that tsar will run as root
-
-FILES
-       /etc/tsar/tsar.conf
-              Configuration file for tsar.output mod list for differnt type
-
-       /etc/tsar/cron.d/*.conf
-              extrat config file, usually tsar devel modules config
-
-BUGS
-       If you find any, please send email to the kongjian@taobao.com
-
-* Get and deploy tsar
-
-see: http://code.taobao.org/trac/tsar/wiki/ZhWikiStart
-
-* Contribution
-
-We are avtively looking for contributors so if you have any ideas, bug reports, or patchs you would like to contribute please do not hesitate to do so.
diff --git a/README.md b/README.md
index 20c10ae..7bffb1d 100644
--- a/README.md
+++ b/README.md
@@ -1,124 +1,155 @@
-Tsar介绍
+Introduction
 ------------
-Tsar是淘宝的一个用来收集服务器系统和应用信息的采集报告工具，如收集服务器的系统信息（cpu，mem等），以及应用数据（nginx、swift等），收集到的数据存储在服务器磁盘上，可以随时查询历史信息，也可以将数据发送到nagios报警。
+Tsar (Taobao System Activity Reporter) is a monitoring tool, which can be used to gather and summarize system information, e.g. CPU, load, IO, and application information, e.g. nginx, HAProxy, Squid, etc. The results can be stored at local disk or sent to Nagios.
 
-Tsar能够比较方便的增加模块，只需要按照tsar的要求编写数据的采集函数和展现函数，就可以把自定义的模块加入到tsar中。
+Tsar can be easily extended by writing modules, which makes it a powerful and versatile reporting tool.
 
-安装
--------------
-Tsar目前托管在github上，下载编译安装步骤:
+Module introduction: [info](https://github.com/alibaba/tsar/blob/master/info.md)
 
-    $git clone git://github.com/kongjian/tsar.git
-    $cd tsar
-    $make
-    $make install
+Installation
+-------------
+Tsar is available on GitHub, you can clone and install it as follows:
 
-安装后：
+    $ git clone https://github.com/alibaba/tsar.git
+    $ cd tsar
+    $ make
+    # make install
 
-定时任务配置:`/etc/cron.d/tsar`，负责每分钟调用tsar执行采集任务；
+Or you can download the zip file and install it:
 
-日志文件轮转配置:`/etc/logrotate.d/tsar`，每个月会把tsar的本地存储进行轮转；
+    $ wget -O tsar.zip https://github.com/alibaba/tsar/archive/master.zip --no-check-certificate
+    $ unzip tsar.zip
+    $ cd tsar
+    $ make
+    # make install
 
-Tsar配置文件路径：`/etc/tsar/tsar.conf`，tsar的采集模块和输出的具体配置；
+After installation, you may see these files:
 
-模块路径：`/usr/local/tsar/modules`，各个模块的动态库so文件；
+* `/etc/tsar/tsar.conf`, which is tsar's main configuration file;
+* `/etc/cron.d/tsar`, is used to run tsar to collect information every minute;
+* `/etc/logrotate.d/tsar` will rotate tsar's log files every month;
+* `/usr/local/tsar/modules` is the directory where all module libraries (*.so) are located;
 
-Tsar配置
--------------
-Tsar刚安装完，还没有历史数据，想要check是否正常，执行tsar -l，查看是否有实时信息输出：
-
-    [kongjian@v132172.sqa.cm4 tsar]$ tsar -l -i 1
-    Time              ---cpu-- ---mem-- ---tcp-- -----traffic---- --xvda-- -xvda1-- -xvda2-- -xvda3-- -xvda4-- -xvda5--  ---load- 
-    Time                util     util   retran    pktin  pktout     util     util     util     util     util     util     load1   
-    11/04/13-14:09:10   0.20    11.57     0.00     9.00    2.00     0.00     0.00     0.00     0.00     0.00     0.00      0.00   
-    11/04/13-14:09:11   0.20    11.57     0.00     4.00    2.00     0.00     0.00     0.00     0.00     0.00     0.00      0.00   
-
-Tsar的配置主要都在`/etc/tsar/tsar.conf`中，常用的有：
-* 增加一个模块,添加 `mod_<yourmodname> on` 到配置文件中
-* 打开或者关闭一个模块,修改`mod_<yourmodname> on/off`
-* `output_stdio_mod` 能够配置执行tsar时的输出模块
-* `output_file_path` 采集到的数据默认保存到的文件（如果修改的话需要对应修改轮转的配置`/etc/logrotate.d/tsar`）
-* `output_interface` 指定tsar的数据输出目的，默认file保存本地，nagios/db输出到监控中心/数据库中，这两个功能还需要结合其它配置，具体见后面
-
-Tsar使用
+Configuration
 -------------
-* 查看历史数据，tsar  
-* -l/--list 查看可用的模块列表
-* -l/--live 查看实时数据,tsar -l --cpu
-* -i/--interval 指定间隔，历史,tsar -i 1 --cpu
-* --modname 指定模块,tsar --cpu
-* -s/--spec 指定字段,tsar --cpu -s sys,util
-* -d/--date 指定日期,YYYYMMDD或者n代表n天前
-* -C/--check 查看最后一次的采集数据
-* -d/--detail 能够指定查看主要字段还是模块的所有字段
-* -h/--help 帮助功能
-* 
-
-高级功能
--------------
-* 输出到nagios
-
-配置：
-首先配置`output_interface file,nagios`，增加nagios输出
-
-然后配置nagios服务器和端口，以及发送的间隔时间
-
-    ####The IP address or the host running the NSCA daemon
+There is no output displayed after installation by default. Just run `tsar -l` to see if the real-time monitoring works, for instance:
+
+    [kongjian@tsar]$ tsar -l -i 1
+    Time              ---cpu-- ---mem-- ---tcp-- -----traffic---- --xvda-- -xvda1-- -xvda2-- -xvda3-- -xvda4-- -xvda5--  ---load-
+    Time                util     util   retran    pktin  pktout     util     util     util     util     util     util     load1
+    11/04/13-14:09:10   0.20    11.57     0.00     9.00    2.00     0.00     0.00     0.00     0.00     0.00     0.00      0.00
+    11/04/13-14:09:11   0.20    11.57     0.00     4.00    2.00     0.00     0.00     0.00     0.00     0.00     0.00      0.00
+
+Usually, we configure Tsar by simply editing `/etc/tsar/tsar.conf`:
+
+* To add a module, add a line like `mod_<yourmodname> on`
+* To enable or disable a module, use `mod_<yourmodname> on/off`
+* To specify parameters for a module, use `mod_<yourmodname> on parameter`
+* `output_stdio_mod` is to set modules output to standard I/O
+* `output_file_path` is to set history data file, (you should modify the logrotate script `/etc/logrotate.d/tsar` too)
+* `output_interface` specifies tsar data output destination, which by default is a local file. See the Advanced section for more information.
+
+Usage
+------
+* null          :see default mods history data, `tsar`
+* --modname     :specify module to show, `tsar --cpu`
+* -L/--list     :list available module, `tsar -L`
+* -l/--live     :show real-time info, `tsar -l --cpu`
+* -i/--interval :set interval for report, `tsar -i 1 --cpu`
+* -s/--spec     :specify module detail field, `tsar --cpu -s sys,util`
+* -D/--detail   :do not conver data to K/M/G, `tsar --mem -D`
+* -m/--merge    :merge multiply item to one, `tsar --io -m`
+* -I/--item     :show spec item data, `tsar --io -I sda`
+* -d/--date     :specify data, YYYYMMDD, or n means n days ago
+* -C/--check    :show the last collect data
+* -h/--help     :show help, `tsar -h`
+
+Advanced
+--------
+* Output to Nagios
+
+To turn it on, just set output type `output_interface file,nagios` in the main configuration file.
+
+You should also specify Nagios' IP address, port, and sending interval, e.g.:
+
+    ####The IP address or the hostname running the NSCA daemon
     server_addr nagios.server.com
-    ####The port on which the daemon is running - default is 5667
+    ####The port on which the daemon is listening - by default it is 5667
     server_port 8086
-    ####The cycle of send alert to nagios
+    ####The cycle (interval) of sending alerts to Nagios
     cycle_time 300
-    
-由于是nagios的被动监控模式，需要制定nsca的位置和配置文件位置
+
+As tsar uses Nagios' passive mode, so you should specify the nsca binary and its configuration file, e.g.:
 
     ####nsca client program
     send_nsca_cmd /usr/bin/send_nsca
     send_nsca_conf /home/a/conf/amon/send_nsca.conf
-    
-接下来制定哪些模块和字段需要进行监控，一共四个阀值对应nagios中的不同报警级别
+
+Then specify the module and fields to be checked. There are 4 threshold levels.
 
     ####tsar mod alert config file
-    ####threshold [hostname.]servicename.key;w-min;w-max;c-min;cmax;
+    ####threshold servicename.key;w-min;w-max;c-min;cmax;
     threshold cpu.util;50;60;70;80;
 
-* 输出到mysql
+* Output to MySQL
 
-配置：
-首先配置`output_interface file,db`，增加db输出
+To use this feature, just add output type `output_interface file,db` in tsar's configuration file.
 
-然后配置哪些模块数据需要输出
+Then specify which module(s) will be enabled:
 
     output_db_mod mod_cpu,mod_mem,mod_traffic,mod_load,mod_tcp,mod_udpmod_io
 
-然后配置sql语句发送的目的地址和端口
+Note that you should set the IP address (or hostname) and port where tsar2db listens, e.g.:
 
     output_db_addr console2:56677
-    
-目的地址在该端口监听tcp数据，并且把数据入库即可，可以参照tsar2db：https://github.com/kongjian/tsar2db
 
-模块开发
--------------
-Tsar的一个比较好的功能是能够增加自己的采集，这时候需要编写模块代码，编译成so文件即可。
+Tsar2db receives sql data and flush it to MySQL. You can find more information about tsar2db at https://github.com/alibaba/tsar2db.
 
-首先安装tsardevel，刚才安装时，如果执行`make tsardevel`，就会把模块开发的基本文件安装到系统
-然后执行tsardevel <yourmodname>，就能在当前模块生成一个模块目录：
 
-    [kongjian@v132172.sqa.cm4 tsar]$ tsardevel test 
-    build:make
-    install:make install
-    uninstall:make uninstall
-    [kongjian@v132172.sqa.cm4 tsar]$ ls test
-    Makefile  mod_test.c  mod_test.conf
+Module development
+------------------
+Tsar is easily extended. Whenever you want information that is not collected by tsar yet, you can write a module with `C` or `Lua`.
 
-按照要求修改mod_test.c中的read_test_stats，set_test_record
-完成后make;make install就完成新模块的配置文件和so的设置，执行tsar --test就能查看效果
+C Module
+--------
+First, install the tsardevel tool (`make tsardevel` will do this for you):
 
-另外也可以通过配置文件对自定义模块传递参数，方法是
-修改配置文件中的`mod_test on myparameter`
-然后在mod_test.c中的read_test_stats函数中，通过parameter参数就可以获得刚才配置文件中的内容
+Then run `tsardevel <yourmodname>`, and you will get a directory named yourmodname, e.g.:
 
-其它
--------------
-Taocode地址：http://code.taobao.org/p/tsar/
-有其它问题请联系：kongjian@taobao.com
+````bash
+[kongjian@tsar]$ tsardevel test
+build:make
+install:make install
+uninstall:make uninstall
+
+[kongjian@tsar]$ ls test
+Makefile  mod_test.c  mod_test.conf
+````
+
+You can modify the read_test_stats() and set_test_record() functions in mod_test.c as you need.
+Then run `make;make install` to install your module and run `tsar --yourmodname` to see the output.
+
+Lua Module
+----------
+First, install the tsarluadevel tool (`make tsarluadevel` will do this for you):
+
+Then run `tsarluadevel <yourmodname>`, and you will get a directory named yourmodname, e.g.:
+
+````bash
+[kongjian@tsar]$ tsarluadevel test
+install:make install
+uninstall:make uninstall
+test:tsar --list or tsar --lua_test --live -i 1
+
+[kongjian@tsar]$ ls test
+Makefile  mod_lua_test.conf  mod_lua_test.lua
+````
+
+You can modify the register()、read() and set() functions in mod_lua_test.lua as you need.
+Then run `make install` to install your module and run `tsar --lua_yourmodname` to see the output.
+
+More
+----
+Homepage http://tsar.taobao.org
+
+Any question, please feel free to contact me by kongjian@taobao.com
diff --git a/README_cn.md b/README_cn.md
new file mode 100644
index 0000000..c376922
--- /dev/null
+++ b/README_cn.md
@@ -0,0 +1,146 @@
+Tsar介绍
+------------
+Tsar是淘宝的一个用来收集服务器系统和应用信息的采集报告工具，如收集服务器的系统信息（cpu，mem等），以及应用数据（nginx、swift等），收集到的数据存储在服务器磁盘上，可以随时查询历史信息，也可以将数据发送到nagios报警。
+
+Tsar能够比较方便的增加模块，只需要按照tsar的要求编写数据的采集函数和展现函数，就可以把自定义的模块加入到tsar中。
+
+安装
+-------------
+Tsar目前托管在github上，下载编译安装步骤:
+
+    $git clone git://github.com/kongjian/tsar.git
+    $cd tsar
+    $make
+    $make install
+
+安装后：
+
+定时任务配置:`/etc/cron.d/tsar`，负责每分钟调用tsar执行采集任务；
+
+日志文件轮转配置:`/etc/logrotate.d/tsar`，每个月会把tsar的本地存储进行轮转；
+
+Tsar配置文件路径：`/etc/tsar/tsar.conf`，tsar的采集模块和输出的具体配置；
+
+模块路径：`/usr/local/tsar/modules`，各个模块的动态库so文件；
+
+Tsar配置
+-------------
+Tsar刚安装完，还没有历史数据，想要check是否正常，执行tsar -l，查看是否有实时信息输出：
+
+    [kongjian@v132172.sqa.cm4 tsar]$ tsar -l -i 1
+    Time              ---cpu-- ---mem-- ---tcp-- -----traffic---- --xvda-- -xvda1-- -xvda2-- -xvda3-- -xvda4-- -xvda5--  ---load-
+    Time                util     util   retran    pktin  pktout     util     util     util     util     util     util     load1
+    11/04/13-14:09:10   0.20    11.57     0.00     9.00    2.00     0.00     0.00     0.00     0.00     0.00     0.00      0.00
+    11/04/13-14:09:11   0.20    11.57     0.00     4.00    2.00     0.00     0.00     0.00     0.00     0.00     0.00      0.00
+
+Tsar的配置主要都在`/etc/tsar/tsar.conf`中，常用的有：
+* 增加一个模块,添加 `mod_<yourmodname> on` 到配置文件中
+* 打开或者关闭一个模块,修改`mod_<yourmodname> on/off`
+* `output_stdio_mod` 能够配置执行tsar时的输出模块
+* `output_file_path` 采集到的数据默认保存到的文件（如果修改的话需要对应修改轮转的配置`/etc/logrotate.d/tsar`）
+* `output_interface` 指定tsar的数据输出目的，默认file保存本地，nagios/db输出到监控中心/数据库中，这两个功能还需要结合其它配置，具体见后面
+
+Tsar使用
+-------------
+* 查看历史数据，tsar
+* -l/--list 查看可用的模块列表
+* -l/--live 查看实时数据,tsar -l --cpu
+* -i/--interval 指定间隔，历史,tsar -i 1 --cpu
+* --modname 指定模块,tsar --cpu
+* -s/--spec 指定字段,tsar --cpu -s sys,util
+* -d/--date 指定日期,YYYYMMDD或者n代表n天前
+* -C/--check 查看最后一次的采集数据
+* -d/--detail 能够指定查看主要字段还是模块的所有字段
+* -h/--help 帮助功能
+
+高级功能
+-------------
+* 输出到nagios
+
+配置：
+首先配置`output_interface file,nagios`，增加nagios输出
+
+然后配置nagios服务器和端口，以及发送的间隔时间
+
+    ####The IP address or the host running the NSCA daemon
+    server_addr nagios.server.com
+    ####The port on which the daemon is running - default is 5667
+    server_port 8086
+    ####The cycle of send alert to nagios
+    cycle_time 300
+
+由于是nagios的被动监控模式，需要制定nsca的位置和配置文件位置
+
+    ####nsca client program
+    send_nsca_cmd /usr/bin/send_nsca
+    send_nsca_conf /home/a/conf/amon/send_nsca.conf
+
+接下来制定哪些模块和字段需要进行监控，一共四个阀值对应nagios中的不同报警级别
+
+    ####tsar mod alert config file
+    ####threshold servicename.key;w-min;w-max;c-min;cmax;
+    threshold cpu.util;50;60;70;80;
+
+* 输出到mysql
+
+配置：
+首先配置`output_interface file,db`，增加db输出
+
+然后配置哪些模块数据需要输出
+
+    output_db_mod mod_cpu,mod_mem,mod_traffic,mod_load,mod_tcp,mod_udpmod_io
+
+然后配置sql语句发送的目的地址和端口
+
+    output_db_addr console2:56677
+
+目的地址在该端口监听tcp数据，并且把数据入库即可，可以参照tsar2db：https://github.com/kongjian/tsar2db
+
+模块开发
+-------------
+Tsar的一个比较好的功能是能够增加自己的采集，这时候需要编写模块代码，编译成so文件即可。
+
+C模块
+-----
+首先安装tsardevel，刚才安装时，如果执行`make tsardevel`，就会把模块开发的基本文件安装到系统
+然后执行tsardevel <yourmodname>，就能在当前模块生成一个模块目录：
+
+````bash
+[kongjian@v132172.sqa.cm4 tsar]$ tsardevel test
+build:make
+install:make install
+uninstall:make uninstall
+
+[kongjian@v132172.sqa.cm4 tsar]$ ls test
+Makefile  mod_test.c  mod_test.conf
+````
+
+按照要求修改mod_test.c中的read_test_stats，set_test_record
+完成后`make;make install`就完成新模块的配置文件和so的设置，执行`tsar --yourmodname`就能查看效果
+
+另外也可以通过配置文件对自定义模块传递参数，方法是
+修改配置文件中的`mod_test on myparameter`
+然后在mod_test.c中的read_test_stats函数中，通过parameter参数就可以获得刚才配置文件中的内容
+
+Lua模块
+-------
+首先安装tsarluadevel，刚才安装时，如果执行`make tsarluadevel`，就会把Lua模块开发的基本文件安装到系统
+然后执行tsarluadevel <yourmodname>，就能在当前模块生成一个模块目录：
+
+````bash
+[kongjian@v132172.sqa.cm4 tsar]$ tsarluadevel test
+install:make install
+uninstall:make uninstall
+test:tsar --list or tsar --lua_test --live -i 1
+
+[kongjian@v132172.sqa.cm4 tsar]$ ls test
+Makefile  mod_lua_test.conf  mod_lua_test.lua
+````
+
+按照要求修改mod_lua_test.lua中的register()，read()和set()函数
+完成后`make install`就完成新模块的安装，执行`tsar --lua_yourmodname`就能查看效果
+
+其它
+-------------
+Taocode地址：http://code.taobao.org/p/tsar/
+有其它问题请联系：kongjian@taobao.com
diff --git a/conf/tsar.conf b/conf/tsar.conf
index 8a6455a..4eee274 100644
--- a/conf/tsar.conf
+++ b/conf/tsar.conf
@@ -17,12 +17,12 @@ mod_lvs off
 mod_haproxy off
 mod_squid off
 mod_nginx off
-mod_swift off
-mod_swift_store off
-mod_swift_fwd off
-mod_swift_code off
-mod_tmd off
 mod_percpu off
+mod_proc off pidname
+
+#lua package path
+lua_package_path /usr/local/tsar/lualib/?.lua
+lua_package_cpath /usr/local/tsar/lualib/?.so
 
 ####output_interface file,db,nagios
 output_interface file
@@ -34,9 +34,14 @@ output_file_path /var/log/tsar.data
 output_stdio_mod mod_swap,mod_partition,mod_cpu,mod_mem,mod_lvs,mod_haproxy,mod_traffic,mod_squid,mod_load,mod_tcp,mod_udp,mod_tcpx,mod_apache,mod_pcsw,mod_io,mod_percpu
 
 ####[output_db]
-#output_db_mod mod_swap,mod_partition,mod_cpu,mod_mem,mod_lvs,mod_haproxy,mod_traffic,mod_squid,mod_load,mod_tcp,mod_udp,mod_tcpx,mod_apache,mod_pcsw,mod_io
+#output_db_mod mod_swap,mod_partition,mod_cpu,mod_mem,mod_traffic,mod_load,mod_tcp,mod_udp,mod_pcsw,mod_io
 #output_db_addr console2:56677
 
+####[output_tcp]
+#output_tcp_mod mod_swap,mod_cpu
+#output_tcp_addr localhost:9666
+#output_tcp_merge on
+
 ####support include other mod conf
 include /etc/tsar/conf.d/*.conf
 
@@ -51,5 +56,5 @@ include /etc/tsar/conf.d/*.conf
 #send_nsca_conf /home/a/conf/amon/send_nsca.conf
 
 ####tsar mod alert config file
-####threshold [hostname.]servicename.key;w-min;w-max;c-min;cmax;
+####threshold servicename.key;w-min;w-max;c-min;cmax;
 #threshold cpu.util;N;N;N;N;
diff --git a/devel/Makefile.test b/devel/Makefile.test
index 2150b99..fb12781 100644
--- a/devel/Makefile.test
+++ b/devel/Makefile.test
@@ -1,4 +1,4 @@
-CFLAGS = -Wall -fPIC --shared -g
+CFLAGS = -Wall -fPIC --shared -g -O2
 CC = gcc
 INCLUDE_DIR = /usr/local/tsar/devel
 LINK = $(CC) -I$(INCLUDE_DIR) $(CFLAGS)
diff --git a/devel/mod_test.c b/devel/mod_test.c
index c6168ac..6b970d4 100644
--- a/devel/mod_test.c
+++ b/devel/mod_test.c
@@ -1,3 +1,4 @@
+
 /*
  * (C) 2010-2011 Alibaba Group Holding Limited
  *
@@ -15,61 +16,69 @@
  *
  */
 
+
 #include "tsar.h"
 
+#define STATS_TEST_SIZE (sizeof(struct stats_test))
+
+static const char *test_usage = "    --test               test information";
+
 /*
- * Structure for test infomation.
+ * temp structure for collection infomation.
  */
 struct stats_test {
-	unsigned long long value_1;
-	unsigned long long value_2;
-	unsigned long long value_3;
+    unsigned long long    value_1;
+    unsigned long long    value_2;
+    unsigned long long    value_3;
 };
 
-#define STATS_TEST_SIZE (sizeof(struct stats_test))
-
-static char *test_usage = "    --test               test information";
-
+/* Structure for tsar */
+static struct mod_info test_info[] = {
+    {"value1", SUMMARY_BIT,  0,  STATS_NULL},
+    {"value2", DETAIL_BIT,  0,  STATS_NULL},
+    {"value3", DETAIL_BIT,  0,  STATS_NULL}
+};
 
-static void read_test_stats(struct module *mod, char *parameter)
+static void
+read_test_stats(struct module *mod, const char *parameter)
 {
-	char buf[256];
-	memset(buf, 0, sizeof(buf));
-	struct stats_test st_test;
-	memset(&st_test, 0, sizeof(struct stats_test));
+    /* parameter actually equals to mod->parameter */
+    char               buf[256];
+    struct stats_test  st_test;
 
-	st_test.value_1 = 1;
-	st_test.value_2 = 1;
-	st_test.value_3 = 1;
+    memset(buf, 0, sizeof(buf));
+    memset(&st_test, 0, sizeof(struct stats_test));
 
-	int pos = sprintf(buf, "%llu,%llu,%llu",
-			/* the store order is not same as read procedure */
-			st_test.value_1,
-			st_test.value_2,
-			st_test.value_3);
+    st_test.value_1 = 1;
+    st_test.value_2 = 1;
+    st_test.value_3 = 1;
 
-	buf[pos] = '\0';
-	set_mod_record(mod, buf);
-	return;
-}
+    int pos = sprintf(buf, "%llu,%llu,%llu",
+            /* the store order is not same as read procedure */
+            st_test.value_1,
+            st_test.value_2,
+            st_test.value_3);
 
-static struct mod_info test_info[] = {
-	{"value1", SUMMARY_BIT,  0,  STATS_NULL},
-	{"value2", DETAIL_BIT,  0,  STATS_NULL},
-	{"value3", DETAIL_BIT,  0,  STATS_NULL}
-};
+    buf[pos] = '\0';
+    /* send data to tsar you can get it by pre_array&cur_array at set_test_record */
+    set_mod_record(mod, buf);
+    return;
+}
 
-static void set_test_record(struct module *mod, double st_array[],
-		U_64 pre_array[], U_64 cur_array[], int inter)
+static void
+set_test_record(struct module *mod, double st_array[],
+    U_64 pre_array[], U_64 cur_array[], int inter)
 {
-	int i;
-	/* set st record */
-	for (i = 0; i < mod->n_col; i++) {
-		st_array[i] = cur_array[i];
-	}
+    int i;
+    /* set st record */
+    for (i = 0; i < mod->n_col; i++) {
+        st_array[i] = cur_array[i];
+    }
 }
 
-void mod_register(struct module *mod)
+/* register mod to tsar */
+void
+mod_register(struct module *mod)
 {
-	register_mod_fileds(mod, "--test", test_usage, test_info, 3, read_test_stats, set_test_record);
+    register_mod_fields(mod, "--test", test_usage, test_info, 3, read_test_stats, set_test_record);
 }
diff --git a/devel/tsar.h b/devel/tsar.h
index 8c650e4..0edab9b 100644
--- a/devel/tsar.h
+++ b/devel/tsar.h
@@ -1,3 +1,4 @@
+
 /*
  * (C) 2010-2011 Alibaba Group Holding Limited
  *
@@ -15,9 +16,11 @@
  *
  */
 
+
 #ifndef _TSARMOD_H
 #define _TSARMOD_H
 
+
 #include <string.h>
 #include <unistd.h>
 #include <stdlib.h>
@@ -31,84 +34,88 @@
 #include <ctype.h>
 #include <sys/stat.h>
 
-#define	U_64		unsigned long long
 
-#define LEN_32		32
-#define LEN_64		64
-#define LEN_128		128
-#define LEN_256		256
-#define LEN_512		512
-#define LEN_1024	1024
-#define LEN_4096	4096
+#define U_64        unsigned long long
+
+#define LEN_32      32
+#define LEN_64      64
+#define LEN_128     128
+#define LEN_256     256
+#define LEN_512     512
+#define LEN_1024    1024
+#define LEN_4096    4096
+#define LEN_1M      1048576
 
 #define ITEM_SPLIT      ";"
 #define DATA_SPLIT      ","
 
 
 struct mod_info {
-	char    hdr[LEN_128];
-	int     summary_bit;    /* bit set indefi summary */
-	int     merge_mode;
-	int     stats_opt;
+    char   hdr[LEN_128];
+    int    summary_bit;    /* bit set indefi summary */
+    int    merge_mode;
+    int    stats_opt;
 };
-struct module
-{
-	char    name[LEN_32];
-	char    opt_line[LEN_32];
-	char    record[LEN_1024];
-	char    usage[LEN_256];
-	char    parameter[LEN_256];
-
-	struct  mod_info *info;
-	void    *lib;
-	int     enable;
-	int     spec;
-
-	/* private data used by framework*/
-	int     n_item;
-	int     n_col;
-	long    n_record;
-
-	int     pre_flag:4;
-	int     st_flag:4;
-
-	U_64    *pre_array;
-	U_64    *cur_array;
-	double  *st_array;
-	double  *max_array;
-	double  *mean_array;
-	double  *min_array;
-
-	/* callback function of module */
-	void (*data_collect) (struct module *,char *);
-	void (*set_st_record) (struct module *mod, double *, U_64 *, U_64 *, int );
-
-	/* mod manage */
-	void (*mod_register) (struct module *);
+
+struct module {
+
+    char    name[LEN_32];
+    char    opt_line[LEN_32];
+    char    record[LEN_1M];
+    char    usage[LEN_256];
+    char    parameter[LEN_256];
+    char    print_item[LEN_256];
+
+    struct  mod_info *info;
+    void   *lib;
+    int     enable;
+    int     spec;
+    int     p_item;
+
+    /* private data used by framework*/
+    int     n_item;
+    int     n_col;
+    long    n_record;
+
+    int     pre_flag:4;
+    int     st_flag:4;
+
+    U_64   *pre_array;
+    U_64   *cur_array;
+    double *st_array;
+    double *max_array;
+    double *mean_array;
+    double *min_array;
+
+    /* callback function of module */
+    void (*data_collect) (struct module *, char *);
+    void (*set_st_record) (struct module *, double *, U_64 *, U_64 *, int);
+
+    /* mod manage */
+    void (*mod_register) (struct module *);
 };
 
-void register_mod_fileds(struct module *mod, char *opt, char *usage,
-		struct mod_info *info, int n_col, void *data_collect, void *set_st_record);
-void set_mod_record(struct module *mod, char *record);
+void register_mod_fields(struct module *mod, const char *opt, const char *usage,
+        struct mod_info *info, int n_col, void *data_collect, void *set_st_record);
+void set_mod_record(struct module *mod, const char *record);
 
 enum {
-	HIDE_BIT,
-	DETAIL_BIT,
-	SUMMARY_BIT,
-	SPEC_BIT
+    HIDE_BIT,
+    DETAIL_BIT,
+    SUMMARY_BIT,
+    SPEC_BIT
 };
 
-
 enum {
-	MERGE_NULL,
-	MERGE_SUM,
-	MERGE_AVG
+    MERGE_NULL,
+    MERGE_SUM,
+    MERGE_AVG
 };
 
 enum {
-	STATS_NULL,
-	STATS_SUB,
-	STATS_SUB_INTER
+    STATS_NULL,
+    STATS_SUB,
+    STATS_SUB_INTER
 };
 
 #endif
diff --git a/devel/tsardevel b/devel/tsardevel
index 50dfb62..8a0ecce 100755
--- a/devel/tsardevel
+++ b/devel/tsardevel
@@ -4,7 +4,7 @@
 usage()
 {
   echo "Usage:"
-  echo "tsarmod modname"
+  echo "tsardevel modname"
   exit 0
 }
 install()
@@ -20,12 +20,23 @@ then
 fi
 
 modname=$1
+install_path='/usr/local/tsar/devel'
+
+for file in mod_test.c mod_test.conf Makefile.test
+do
+ if [ ! -e "$install_path/$file" ] ;then
+  echo "$install_path/$file not exist!"
+  echo "make sure you have run 'make tsardevel' when install tsar."
+  exit 1
+ fi
+done
+
 
 # mk new mod_test
-mkdir $modname
-sed -e "s/test/$modname/g" < /usr/local/tsar/devel/mod_test.c > ./$modname/mod_$modname.c
-sed -e "s/test/$modname/g" < /usr/local/tsar/devel/mod_test.conf > ./$modname/mod_$modname.conf
-sed -e "s/test/$modname/g" < /usr/local/tsar/devel/Makefile.test > ./$modname/Makefile
+mkdir -p $modname
+sed -e "s/test/$modname/g" < $install_path/mod_test.c > ./$modname/mod_$modname.c
+sed -e "s/test/$modname/g" < $install_path/mod_test.conf > ./$modname/mod_$modname.conf
+sed -e "s/test/$modname/g" < $install_path/Makefile.test > ./$modname/Makefile
 if [ $? -eq 0 ]
 then
  install
diff --git a/examples/tsar-lua-nginx/Makefile b/examples/tsar-lua-nginx/Makefile
new file mode 100644
index 0000000..558b517
--- /dev/null
+++ b/examples/tsar-lua-nginx/Makefile
@@ -0,0 +1,8 @@
+install:
+	mkdir -p /etc/tsar/conf.d/
+	cp ./mod_lua_nginx.lua /usr/local/tsar/modules/
+	cp ./mod_lua_nginx.conf /etc/tsar/conf.d/lua_nginx.conf
+
+uninstall:
+	rm /usr/local/tsar/modules/mod_lua_nginx.lua
+	rm /etc/tsar/conf.d/lua_nginx.conf
diff --git a/examples/tsar-lua-nginx/mod_lua_nginx.conf b/examples/tsar-lua-nginx/mod_lua_nginx.conf
new file mode 100644
index 0000000..313ef01
--- /dev/null
+++ b/examples/tsar-lua-nginx/mod_lua_nginx.conf
@@ -0,0 +1,15 @@
+mod_lua_nginx on
+
+####add it to tsar default output
+output_stdio_mod mod_lua_nginx
+
+####add it to center db
+#output_db_mod mod_lua_nginx
+
+####add it to nagios send
+####set nagios threshold for alert
+#output_nagios_mod mod_lua_nginx
+
+#threshold lua_nginx.value1;N;N;N;N;
+#threshold lua_nginx.value2;N;N;N;N;
+#threshold lua_nginx.value3;N;N;N;N;
diff --git a/examples/tsar-lua-nginx/mod_lua_nginx.lua b/examples/tsar-lua-nginx/mod_lua_nginx.lua
new file mode 100644
index 0000000..1d6645b
--- /dev/null
+++ b/examples/tsar-lua-nginx/mod_lua_nginx.lua
@@ -0,0 +1,128 @@
+local _M = {
+    _VERSION = "0.1.0"
+}
+
+local cjson = require("cjson")
+local socket = require("socket")
+local http = require("socket.http")
+local ltn12 = require("ltn12")
+local DETAIL_BIT = tsar.DETAIL_BIT
+local SUMMARY_BIT = tsar.SUMMARY_BIT
+local HIDE_BIT = tsar.HIDE_BIT
+local STATS_NULL = tsar.STATS_NULL
+local STATS_SUB = tsar.STATS_SUB
+local STATS_SUB_INTER = tsar.STATS_SUB_INTER
+local string_format = string.format
+local string_match = string.match
+local string_find = string.find
+local concat = table.concat
+
+local info = {
+    {hdr = "accept", summary_bit = DETAIL_BIT,  merge_mode = 0, stats_opt = STATS_SUB},
+    {hdr = "handle", summary_bit = DETAIL_BIT,  merge_mode = 0, stats_opt = STATS_SUB},
+    {hdr = "  reqs", summary_bit = DETAIL_BIT,  merge_mode = 0, stats_opt = STATS_SUB},
+    {hdr = "active", summary_bit = DETAIL_BIT,  merge_mode = 0, stats_opt = STATS_NULL},
+    {hdr = "  read", summary_bit = DETAIL_BIT,  merge_mode = 0, stats_opt = STATS_NULL},
+    {hdr = " write", summary_bit = DETAIL_BIT,  merge_mode = 0, stats_opt = STATS_NULL},
+    {hdr = "  wait", summary_bit = DETAIL_BIT,  merge_mode = 0, stats_opt = STATS_NULL},
+    {hdr = "   qps", summary_bit = SUMMARY_BIT, merge_mode = 0, stats_opt = STATS_SUB_INTER},
+    {hdr = "    rt", summary_bit = SUMMARY_BIT, merge_mode = 0, stats_opt = STATS_NULL},
+    {hdr = "sslqps", summary_bit = SUMMARY_BIT, merge_mode = 0, stats_opt = STATS_SUB_INTER},
+    {hdr = "spdyps", summary_bit = SUMMARY_BIT, merge_mode = 0, stats_opt = STATS_SUB_INTER},
+    {hdr = "sslhst", summary_bit = SUMMARY_BIT, merge_mode = 0, stats_opt = STATS_NULL},
+    {hdr = "sslhsc", summary_bit = HIDE_BIT,    merge_mode = 0, stats_opt = STATS_NULL},
+}
+
+function _M.read(mod, param)
+    local naccept, nhandled, nrequest, nrstime
+    local result = http.request("http://127.0.0.1/nginx_status")
+
+    local nactive = string_match(result, [[Active connections: (%d+)]])
+    local nreading = string_match(result, [[Reading: (%d+)]])
+    local nwriting = string_match(result, [[Writing: (%d+)]])
+    local nwaiting = string_match(result, [[Waiting: (%d+)]])
+    if string_find(result, [[server accepts handled requests request_time]]) then
+        naccept, nhandled, nrequest, nrstime = string.match(result, "(%d+) (%d+) (%d+) (%d+)")
+    elseif string_find(result, [[server accepts handled requests]]) then
+        naccept, nhandled, nrequest = string.match(result, "(%d+) (%d+) (%d+)")
+    else
+        naccept = string_match(result, "Server accepts: (%d+)")
+        nhandled = string_match(result, "nhandled: (%d+)")
+        nrequest = string_match(result, "requests: (%d+)")
+        nrstime = string_match(result, "request_time: (%d+)")
+    end
+
+    local d = {}
+
+    d[1] = naccept
+    d[2] = nhandled
+    d[3] = nrequest
+    d[4] = nactive
+    d[5] = nreading
+    d[6] = nwriting
+    d[7] = nwaiting
+    d[8] = nrequest
+    d[9] = nrstime
+    d[10] = 0
+    d[11] = 0
+    d[12] = 0
+    d[13] = 0
+
+    return concat(d, ",")
+end
+
+function _M.set(mod, st_array, pre_array, cur_array, interval)
+    for i = 1, 3 do
+        if cur_array[i] >= pre_array[i] then
+            st_array[i] = cur_array[i] - pre_array[i]
+        else
+            st_array[i] = 0
+        end
+    end
+
+    for i = 4, 7 do
+        st_array[i] = cur_array[i]
+    end
+
+    if cur_array[3] >= pre_array[3] then
+        st_array[7] =  (cur_array[3] - pre_array[3]) * 1.0 /  interval
+    else
+        st_array[7] = 0
+    end
+
+    if cur_array[9] >= pre_array[9] then
+        if cur_array[3] > pre_array[3] then
+            st_array[9] =  (cur_array[9] - pre_array[9]) * 1.0 / (cur_array[3] - pre_array[3]);
+        else
+            st_array[9] = 0
+        end
+    end
+
+    for i = 10, 11 do
+        if cur_array[i] >= pre_array[i] then
+            st_array[i] = (cur_array[i] - pre_array[i]) * 1.0 / interval
+        else
+            st_array[i] = 0
+        end
+    end
+
+    if cur_array[12] >= pre_array[12] then
+        if cur_array[12] > pre_array[12] then
+            st_array[12] = (cur_array[12] - pre_array[12]) * 1.0 / (cur_array[13] - pre_array[13])
+        else
+            st_array[12] = 0
+        end
+    end
+
+    return st_array, pre_array, cur_array
+end
+
+function _M.register()
+    return {
+        opt = "--lua_nginx",
+        usage = "nginx statistics",
+        info = info,
+    }
+end
+
+return _M
diff --git a/include/common.h b/include/common.h
index 640a451..b67f21d 100644
--- a/include/common.h
+++ b/include/common.h
@@ -1,3 +1,4 @@
+
 /*
  * (C) 2010-2011 Alibaba Group Holding Limited
  *
@@ -15,16 +16,22 @@
  *
  */
 
-#ifndef _COMMON_H
-#define _COMMON_H
+
+#ifndef TSAR_COMMON_H
+#define TSAR_COMMON_H
+
+
 #define PRE_RECORD_FILE         "/tmp/.tsar.tmp"
+
 /*
  * convert data to array
  */
-int convert_record_to_array(U_64 *array, int l_array, char *record);
-void get_mod_hdr(char hdr[], struct module *mod);
-int strtok_next_item(char item[], char *record, int *start);
+int convert_record_to_array(U_64 *array, int l_array, const char *record);
+void get_mod_hdr(char hdr[], const struct module *mod);
+char* strtok_next_item(char *record, int *start);
 int merge_mult_item_to_array(U_64 *array, struct module *mod);
-int get_strtok_num(char *str, char *split);
+int get_strtok_num(const char *str, const char *split);
 int get_st_array_from_file(int have_collect);
+
+
 #endif
diff --git a/include/config.h b/include/config.h
index 85863bc..c2c786b 100644
--- a/include/config.h
+++ b/include/config.h
@@ -1,3 +1,4 @@
+
 /*
  * (C) 2010-2011 Alibaba Group Holding Limited
  *
@@ -15,60 +16,79 @@
  *
  */
 
-#ifndef _CONFIG_H
-#define _CONFIG_H
+
+#ifndef TSAR_CONFIG_H
+#define TSAR_CONFIG_H
+
 
 #include "define.h"
 
-struct configure
-{
-	/* from arg */
-	int	running_mode;	/* running mode */
-	char	config_file[LEN_128];
-	int	debug_level;
-
-	char	output_interface[LEN_128];  /* which interface will enable*/
-
-	/* output print */
-	char	output_print_mod[LEN_512];  /* which mod will print throught argv */
-	char	output_stdio_mod[LEN_512];  /* which mod will print throuhth conf file */
-	char    output_nagios_mod[LEN_512];  /* which mod will output to nagios */
-	int	print_interval;		 /* how many seconds will escape every print interval */
-	int	print_nline_interval;	 /* how many lines will skip every print interval */
-	int	print_mode;		/* data type will print: summary or detail */
-	int	print_merge;		/* mult items is merge */
-	int	print_detail;		/* conver data to K/M/G */
-	int	print_ndays;		 /* these days will print.default:1 */
-	int	print_day;		 /* which day will print*/
-	int	print_start_time;	/* the start of the print time*/
-	int	print_end_time;		 /* the end of the print time*/
-	int	print_tail;
-	int	print_file_number;	/* which tsar.data file used*/
-
-	/* output db */
-	char	output_db_mod[LEN_512];  /* which mod will output */
-	char	output_db_addr[LEN_512]; /* db addr */
-
-	/* output nagios */
-	char    server_addr[LEN_512];
-	int     *server_port;
-	int     *cycle_time;
-	char    send_nsca_cmd[LEN_512];
-	char    send_nsca_conf[LEN_512];
-
-	char    check_name[MAX_MOD_NUM][LEN_32];
-	float   wmin[MAX_MOD_NUM];
-	float   wmax[MAX_MOD_NUM];
-	float   cmin[MAX_MOD_NUM];
-	float   cmax[MAX_MOD_NUM];
-	int     mod_num;
-
-	/* output file */
-	char	output_file_path[LEN_128];
+
+struct configure {
+
+    /* from arg */
+    int     running_mode;               /* running mode */
+    char    config_file[LEN_128];
+    int     debug_level;
+
+    char    output_interface[LEN_128];  /* which interface will enable*/
+
+    /* output print */
+    char    output_print_mod[LEN_512];  /* which mod will print throught argv */
+    char    output_stdio_mod[LEN_512];  /* which mod will print throuhth conf file */
+    char    output_nagios_mod[LEN_512]; /* which mod will output to nagios */
+    int     print_interval;             /* how many seconds will escape every print interval */
+    int     print_nline_interval;       /* how many lines will skip every print interval */
+    int     print_mode;                 /* data type will print: summary or detail */
+    int     print_merge;                /* mult items is merge */
+    int     print_detail;               /* conver data to K/M/G */
+    int     print_ndays;                /* these days will print.default:1 */
+    int     print_day;                  /* which day will print */
+    int     print_start_time;           /* the start of the print time */
+    int     print_end_time;             /* the end of the print time */
+    int     print_tail;
+    int     print_file_number;          /* which tsar.data file used */
+    int     print_max_day;              /* max day for history print */
+    int     print_nminute;              /* these minutes for history watch */
+
+    /* output db */
+    char    output_db_mod[LEN_512];     /* which mod will output */
+    char    output_db_addr[LEN_512];    /* db addr */
+
+    /* output tcp */
+    int     output_tcp_addr_num;        /*the number of tcp address indeed need to send data*/
+    char    output_tcp_mod[LEN_512];
+    char    output_tcp_addr[MAX_TCP_ADDR_NUM][LEN_256];
+    char    output_tcp_merge[LEN_256];
+
+    /* output nagios */
+    char    server_addr[LEN_512];
+    int     server_port;
+    int     cycle_time;
+    char    send_nsca_cmd[LEN_512];
+    char    send_nsca_conf[LEN_512];
+
+    char    check_name[MAX_MOD_NUM][LEN_32];
+    float   wmin[MAX_MOD_NUM];
+    float   wmax[MAX_MOD_NUM];
+    float   cmin[MAX_MOD_NUM];
+    float   cmax[MAX_MOD_NUM];
+    int     mod_num;
+
+    /* output file */
+    char    output_file_path[LEN_128];
+
+    /* lua package path */
+    char lua_path[LEN_512];
+    char lua_cpath[LEN_512];
 };
 
+
 void parse_config_file(const char *file_name);
 void get_include_conf();
 void get_threshold();
-void set_special_field(char *spec_field);
+void set_special_field(const char *spec_field);
+void set_special_item(const char *spec_field);
+
+
 #endif
diff --git a/include/debug.h b/include/debug.h
index 9eab1c6..5889d31 100644
--- a/include/debug.h
+++ b/include/debug.h
@@ -1,3 +1,4 @@
+
 /*
  * (C) 2010-2011 Alibaba Group Holding Limited
  *
@@ -15,18 +16,25 @@
  *
  */
 
-#ifndef _DEBUG_H
-#define _DEBUG_H
+
+#ifndef TSAR_DEBUG_H
+#define TSAR_DEBUG_H
+
 
 typedef enum
 {
-	LOG_INFO,
-	LOG_DEBUG,
-	LOG_WARN,
-	LOG_ERR,
-	LOG_FATAL
+    LOG_INFO,
+    LOG_DEBUG,
+    LOG_WARN,
+    LOG_ERR,
+    LOG_FATAL
 } log_level_t;
 
 
-void do_debug(log_level_t level, const char *fmt, ...);
+#define do_debug(level, ...) \
+	_do_debug(level, __FILE__, __LINE__, __VA_ARGS__)
+
+void _do_debug(log_level_t level, const char *file, int line, const char *fmt, ...);
+
+
 #endif
diff --git a/include/define.h b/include/define.h
index 1bbd5f5..0d01e14 100644
--- a/include/define.h
+++ b/include/define.h
@@ -1,3 +1,4 @@
+
 /*
  * (C) 2010-2011 Alibaba Group Holding Limited
  *
@@ -15,46 +16,51 @@
  *
  */
 
-#ifndef _DEFINE_H
-#define _DEFINE_H
+
+#ifndef TSAR_DEFINE_H
+#define TSAR_DEFINE_H
+
 
 //-check & --check function for old tsar amon usage
 #define OLDTSAR
 
-#define U_BIT		3
+#define U_BIT       3
 
-#define	U_64		unsigned long long
+#define U_64        unsigned long long
 
-#define LEN_32		32
-#define LEN_64		64
-#define LEN_128		128
-#define LEN_256		256
-#define LEN_512		512
-#define LEN_1024	1024
-#define LEN_4096	4096
-#define LEN_10240	10240
+#define LEN_32      32
+#define LEN_64      64
+#define LEN_128     128
+#define LEN_256     256
+#define LEN_512     512
+#define LEN_1024    1024
+#define LEN_4096    4096
+#define LEN_1M      1048576
+#define LEN_10M     10485760
 
-#define MAX_COL_NUM	64
-#define MAX_MOD_NUM	32
+#define MAX_COL_NUM 64
+#define MAX_MOD_NUM 32
+#define MAX_TCP_ADDR_NUM 4
 
 #define SECTION_SPLIT   "|"
 #define STRING_SPLIT    ":"
-#define ITEM_SPLIT	";"
-#define ITEM_SPSTART	"="
-#define DATA_SPLIT	","
-#define HDR_SPLIT	"#"
+#define ITEM_SPLIT  ";"
+#define ITEM_SPSTART    "="
+#define DATA_SPLIT  ","
+#define PARAM_SPLIT ':'
+#define HDR_SPLIT   "#"
 #define PRINT_DATA_SPLIT "  "
-#define PRINT_SEC_SPLIT	" "
-#define W_SPACE		" \t\r\n"
+#define PRINT_SEC_SPLIT " "
+#define W_SPACE     " \t\r\n"
 
+#define DEFAULT_PRINT_NUM   20
+#define DEFAULT_PRINT_INTERVAL  5
 
-#define DEFAULT_PRINT_NUM	20
-#define DEFAULT_PRINT_INTERVAL	5
+#define MOD_INFO_SIZE       sizeof(strcut mod_info)
 
-#define MOD_INFO_SIZE		sizeof(strcut mod_info)
-
-#define DEFAULT_CONF_FILE_PATH		"/etc/tsar/tsar.conf"
-#define DEFAULT_OUTPUT_FILE_PATH	"/var/log/tsar.data" 
+#define DEFAULT_MODULE_PATH         "/usr/local/tsar/modules"
+#define DEFAULT_CONF_FILE_PATH      "/etc/tsar/tsar.conf"
+#define DEFAULT_OUTPUT_FILE_PATH    "/var/log/tsar.data"
 #define MIN_STRING "MIN:        "
 #define MEAN_STRING "MEAN:       "
 #define MAX_STRING "MAX:        "
@@ -71,68 +77,72 @@
 #define APACHERT "/tmp/apachert.mmap"
 #define TCP "/proc/net/tcp"
 #define NETSTAT "/proc/net/netstat"
+#define MOD_LUA_PREFIX "mod_lua_"
+
 
 enum {
-	MERGE_NOT,
-	MERGE_ITEM
+    MERGE_NOT,
+    MERGE_ITEM
 };
 
 
 enum {
-	RUN_NULL,
-	RUN_LIST,
-	RUN_CRON,
+    RUN_NULL,
+    RUN_LIST,
+    RUN_CRON,
 #ifdef OLDTSAR
-	RUN_CHECK,
-	RUN_CHECK_NEW,
+    RUN_CHECK,
 #endif
-	RUN_PRINT,
-	RUN_PRINT_LIVE
+    RUN_CHECK_NEW,
+    RUN_PRINT,
+    RUN_PRINT_LIVE,
+    RUN_WATCH
 };
 
 
 enum {
-	DATA_NULL,
-	DATA_SUMMARY,
-	DATA_DETAIL,
-	DATA_ALL
+    DATA_NULL,
+    DATA_SUMMARY,
+    DATA_DETAIL,
+    DATA_ALL
 };
 
 
 enum {
-	TAIL_NULL,
-	TAIL_MAX,
-	TAIL_MEAN,
-	TAIL_MIN
+    TAIL_NULL,
+    TAIL_MAX,
+    TAIL_MEAN,
+    TAIL_MIN
 };
 
 
 enum {
-	OUTPUT_NULL,
-	OUTPUT_PRINT,
-	OUTPUT_NAGIOS
+    OUTPUT_NULL,
+    OUTPUT_PRINT,
+    OUTPUT_NAGIOS
 };
 
 
 enum {
-	HIDE_BIT,
-	DETAIL_BIT,
-	SUMMARY_BIT,
-	SPEC_BIT
+    HIDE_BIT,
+    DETAIL_BIT,
+    SUMMARY_BIT,
+    SPEC_BIT
 };
 
 
 enum {
-	MERGE_NULL,
-	MERGE_SUM,
-	MERGE_AVG
+    MERGE_NULL,
+    MERGE_SUM,
+    MERGE_AVG
 };
 
 
 enum {
-	STATS_NULL,
-	STATS_SUB,
-	STATS_SUB_INTER
+    STATS_NULL,
+    STATS_SUB,
+    STATS_SUB_INTER
 };
 
+
 #endif
diff --git a/include/framework.h b/include/framework.h
index a66c227..0a4df0c 100644
--- a/include/framework.h
+++ b/include/framework.h
@@ -1,3 +1,4 @@
+
 /*
  * (C) 2010-2011 Alibaba Group Holding Limited
  *
@@ -15,66 +16,73 @@
  *
  */
 
-#ifndef _FRAMEWORK_H
-#define _FRAMEWORK_H
+
+#ifndef TSAR_FRAMEWORK_H
+#define TSAR_FRAMEWORK_H
+
 
 #include "define.h"
+
 struct mod_info {
-	char	hdr[LEN_128];
-	int	summary_bit;	/* bit set indefi summary */
-	int	merge_mode;
-	int	stats_opt;
+    char    hdr[LEN_128];
+    int     summary_bit;    /* bit set indefi summary */
+    int     merge_mode;
+    int     stats_opt;
 };
 
-struct module
-{
-	char	name[LEN_32];
-	char	opt_line[LEN_32];
-	char	record[LEN_4096];
-	char    usage[LEN_256];
-	char	parameter[LEN_256];
-
-	struct  mod_info *info;
-	void    *lib;
-	int	enable;
-	int	spec;
-
-	/* private data used by framework*/
-	int	n_item;
-	int	n_col;
-	long	n_record;
-
-	int	pre_flag:4;
-	int	st_flag:4;
-
-	U_64	*pre_array;
-	U_64	*cur_array;
-	double	*st_array;
-	double	*max_array;
-	double	*mean_array;
-	double	*min_array;
-
-	/* callback function of module */
-	void (*data_collect) (struct module *,char *);
-	void (*set_st_record) (struct module *mod, double *, U_64 *, U_64 *, int );
-
-	/* mod manage */
-	void (*mod_register) (struct module *);
+struct module {
+
+    char    name[LEN_32];
+    char    opt_line[LEN_32];
+    char    record[LEN_1M];
+    char    usage[LEN_256];
+    char    parameter[LEN_256];
+    char    print_item[LEN_256];
+
+    struct  mod_info *info;
+    void   *lib;
+    int     enable;
+    int     spec;
+    int     p_item;
+
+    /* private data used by framework*/
+    int     n_item;
+    int     n_col;
+    long    n_record;
+
+    int     pre_flag:4;
+    int     st_flag:4;
+
+    U_64   *pre_array;
+    U_64   *cur_array;
+    double *st_array;
+    double *max_array;
+    double *mean_array;
+    double *min_array;
+
+    /* callback function of module */
+    void (*data_collect) (struct module *, char *);
+    void (*set_st_record) (struct module *, double *, U_64 *, U_64 *, int);
+
+    /* mod manage */
+    void (*mod_register) (struct module *);
 };
 
 
-void register_mod_fileds(struct module *mod, char *opt, char *usage,
-		struct mod_info *info, int n_col, void *data_collect, void *set_st_record);
-void set_mod_record(struct module *mod, char *record);
+void register_mod_fields(struct module *mod, const char *opt, const char *usage,
+        struct mod_info *info, int n_col, void *data_collect, void *set_st_record);
+void set_mod_record(struct module *mod, const char *record);
 void init_module_fields();
-int reload_modules(char *s_mod);
+int reload_modules(const char *s_mod);
 #ifdef OLDTSAR
 void reload_check_modules();
 #endif
 void load_modules();
 void free_modules();
 void collect_record();
-void read_line_to_module_record(char *line);
+time_t read_line_to_module_record(char *line);
 int  collect_record_stat();
 void disable_col_zero();
+
+
 #endif
diff --git a/include/output_db.h b/include/output_db.h
index 6271979..e4b3a84 100644
--- a/include/output_db.h
+++ b/include/output_db.h
@@ -1,3 +1,4 @@
+
 /*
  * (C) 2010-2011 Alibaba Group Holding Limited
  *
@@ -15,8 +16,10 @@
  *
  */
 
-#ifndef _OUTPUT_DB_H
-#define _OUTPUT_DB_H
+
+#ifndef TSAR_OUTPUT_DB_H
+#define TSAR_OUTPUT_DB_H
+
 
 #include <netinet/in.h>
 #include <sys/types.h>
@@ -24,6 +27,8 @@
 #include <arpa/inet.h>
 #include <netdb.h>
 
+
 void output_db(int have_collect);
 
+
 #endif
diff --git a/include/output_file.h b/include/output_file.h
index 557490c..dd8ce7f 100644
--- a/include/output_file.h
+++ b/include/output_file.h
@@ -1,3 +1,4 @@
+
 /*
  * (C) 2010-2011 Alibaba Group Holding Limited
  *
@@ -15,22 +16,27 @@
  *
  */
 
-#ifndef _OUTPUT_FILE_H
-#define _OUTPUT_FILE_H
+
+#ifndef TSAR_OUTPUT_FILE_H
+#define TSAR_OUTPUT_FILE_H
+
+
 /*
  * output data to file
  */
 
 struct buffer {
-	char	*data;
-	int	len;
+    char  *data;
+    int    len;
 };
 
-struct file_header
-{
-	int	version;
-	time_t	t_start;	
+struct file_header {
+    int    version;
+    time_t t_start;
 };
 
+
 void output_file();
+
+
 #endif
diff --git a/include/output_nagios.h b/include/output_nagios.h
index a9a63e5..54cdf7f 100644
--- a/include/output_nagios.h
+++ b/include/output_nagios.h
@@ -1,3 +1,4 @@
+
 /*
  * (C) 2010-2011 Alibaba Group Holding Limited
  *
@@ -15,8 +16,10 @@
  *
  */
 
-#ifndef _OUTPUT_NAGIOS_H
-#define _OUTPUT_NAGIOS_H
+
+#ifndef TSAR_OUTPUT_NAGIOS_H
+#define TSAR_OUTPUT_NAGIOS_H
+
 
 #include <netinet/in.h>
 #include <sys/types.h>
@@ -24,5 +27,8 @@
 #include <arpa/inet.h>
 #include <netdb.h>
 
+
 void output_nagios();
+
+
 #endif
diff --git a/include/output_print.h b/include/output_print.h
index 10173aa..0c8e9d9 100644
--- a/include/output_print.h
+++ b/include/output_print.h
@@ -1,3 +1,4 @@
+
 /*
  * (C) 2010-2011 Alibaba Group Holding Limited
  *
@@ -15,12 +16,14 @@
  *
  */
 
-#ifndef _OUT_PRINT_H
-#define _OUT_PRINT_H
+
+#ifndef TSAR_OUT_PRINT_H
+#define TSAR_OUT_PRINT_H
+
+
 /*
  * output data to std output (history or live mode)
  */
-
 void running_print();
 #ifdef OLDTSAR
 void running_current();
@@ -28,4 +31,5 @@ void running_check(int check_type);
 #endif
 void running_print_live();
 
+
 #endif
diff --git a/include/output_tcp.h b/include/output_tcp.h
new file mode 100644
index 0000000..2eba889
--- /dev/null
+++ b/include/output_tcp.h
@@ -0,0 +1,32 @@
+
+/*
+ * (C) 2010-2011 Alibaba Group Holding Limited
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+
+#ifndef TSAR_OUTPUT_TCP_H
+#define TSAR_OUTPUT_TCP_H
+
+
+#include <netinet/in.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <arpa/inet.h>
+
+
+void output_multi_tcp(int have_collect);
+struct sockaddr_in * str2sa(char *);
+#endif
diff --git a/include/public.h b/include/public.h
index 1f1ab4b..f4cfb76 100644
--- a/include/public.h
+++ b/include/public.h
@@ -1,3 +1,4 @@
+
 /*
  * (C) 2010-2011 Alibaba Group Holding Limited
  *
@@ -15,14 +16,17 @@
  *
  */
 
-#ifndef _PUBLIC_H
-#define _PUBLIC_H
+
+#ifndef TSAR_PUBLIC_H
+#define TSAR_PUBLIC_H
+
 
 #include <errno.h>
 #include <math.h>
 #include <ctype.h>
 #include "tsar.h"
 
+
 /*
  * /proc/files
  */
@@ -40,6 +44,7 @@
 #define FINODE_STATE    "/proc/sys/fs/inode-state"
 #define PTY_NR          "/proc/sys/kernel/pty/nr"
 
+
 /*
  *  ANSI Color setting segment
  *
@@ -48,13 +53,14 @@
 #define GREEN_FMT(s) "\033[40;32m"s"\033[0m"
 #define RED_FMT(s) "\033[40;31m"s"\033[0m"
 
-#define COLOR(val, fmt, str, ret, color) do				\
-{							\
-	if ((val) > 100)				\
-	ret = sprintf(str,			\
-			color##_FMT(fmt), (val));	\
-	else						\
-	ret = sprintf(str, fmt, (val));		\
+
+#define COLOR(val, fmt, str, ret, color) do             \
+{                           \
+    if ((val) > 100)                \
+    ret = sprintf(str,          \
+            color##_FMT(fmt), (val));   \
+    else                        \
+    ret = sprintf(str, fmt, (val));     \
 } while(0)
 
 #define FALSE 0
@@ -64,6 +70,7 @@
 #define CURR 0
 #define PAST 1
 
+
 /*
  * for statistics
  */
@@ -80,9 +87,9 @@ enum {MIN, MEAN, MAX};
  */
 #define _S(a, b) (((b) == 0) ? 0 : ((a) / (b)))
 
-#define S_VALUE(m,n,p)  (((double) ((n) - (m))) / (p) )
+#define S_VALUE(m, n, p)  (((double) ((n) - (m))) / (p) )
 
-#define SP_VALUE(m,n,p) (((double) ((n) - (m))) / (p) * 100)
+#define SP_VALUE(m, n, p) (((double) ((n) - (m))) / (p) * 100)
 
 #define SK(K, shift) (((unsigned long long)(K) << 10) >> shift)
 #define SB(B, shift) ((unsigned long long)(B) >> shift)
@@ -107,187 +114,188 @@ enum {MIN, MEAN, MAX};
 /* 1000 */
 #define KB 0x3E8
 
-#define __INDENT(f, idx, ret)				\
-	do {						\
-		if((f/1024.0) > GB) {			\
-			(ret) = (f) * 1.0/1024.0 / GB;	\
-			(idx) = 3;			\
-		}					\
-		else if((f) > GB) {			\
-			(ret) = (f) * 1.0 / GB;		\
-			(idx) = 2;			\
-		}					\
-		else if ((f) > MB){			\
-			(ret) = (f) * 1.0 / MB;		\
-			(idx) = 1;			\
-		}					\
-		else {					\
-			(ret) = (f) * 1.0 / KB;		\
-			(idx) = 0;			\
-		}					\
-	}while(0)
-
-
-#define __PRINT_S(buffer, val, ret) do {			\
-	int _i;						\
-	double _f;					\
-	char u[] = {'K', 'M', 'G', 'T'};		\
-	__INDENT((val), _i, _f);			\
-	(ret) += sprintf((buffer), FMT_S, _f, u[_i]);	\
+#define __INDENT(f, idx, ret)               \
+    do {                        \
+        if((f/1024.0) > GB) {           \
+            (ret) = (f) * 1.0/1024.0 / GB;  \
+            (idx) = 3;          \
+        }                   \
+        else if((f) > GB) {         \
+            (ret) = (f) * 1.0 / GB;     \
+            (idx) = 2;          \
+        }                   \
+        else if ((f) > MB){         \
+            (ret) = (f) * 1.0 / MB;     \
+            (idx) = 1;          \
+        }                   \
+        else {                  \
+            (ret) = (f) * 1.0 / KB;     \
+            (idx) = 0;          \
+        }                   \
+    }while(0)
+
+
+#define __PRINT_S(buffer, val, ret) do {            \
+    int _i;                     \
+    double _f;                  \
+    char u[] = {'K', 'M', 'G', 'T'};        \
+    __INDENT((val), _i, _f);            \
+    (ret) += sprintf((buffer), FMT_S, _f, u[_i]);   \
 }while(0)
 
-#define __PRINT_SP(buffer, val, ret) do {			\
-	(ret) += sprintf(buffer, FMT_SP, (val));	\
+#define __PRINT_SP(buffer, val, ret) do {           \
+    (ret) += sprintf(buffer, FMT_SP, (val));    \
 }while(0)
 
-#define __PRINT_NAGIOS(buffer, val, ret) do {			\
-	(ret) += sprintf(buffer, FMT_NAGIOS, (val));	\
+#define __PRINT_NAGIOS(buffer, val, ret) do {           \
+    (ret) += sprintf(buffer, FMT_NAGIOS, (val));    \
 }while(0)
 
-#define PRINT(buffer, val, ret, type) do {			\
-	if (type == OUTPUT_NAGIOS) {			\
-		__PRINT_NAGIOS(buffer, val, ret);	\
-	}						\
-	else{						\
-		if ((val) < KB)	{			\
-			__PRINT_SP(buffer, val, ret);	\
-		}					\
-		else {					\
-			__PRINT_S(buffer, val, ret);	\
-		}					\
-	}						\
+#define PRINT(buffer, val, ret, type) do {          \
+    if (type == OUTPUT_NAGIOS) {            \
+        __PRINT_NAGIOS(buffer, val, ret);   \
+    }                       \
+    else{                       \
+        if ((val) < KB) {           \
+            __PRINT_SP(buffer, val, ret);   \
+        }                   \
+        else {                  \
+            __PRINT_S(buffer, val, ret);    \
+        }                   \
+    }                       \
 } while(0)
 
-#define myalloc(p, type, size)					\
-	struct type * p = NULL;					\
-p = (struct type *)malloc(size);			\
-if(!p) {						\
-	fprintf(stderr, "failed to alloc memory\n");	\
-	exit(EXIT_FAILURE);				\
-}							\
-memset(p, 0, size)					\
-
-#define BUFFER_ROTATE(mod, size)					\
-	do {								\
-		memcpy(&s_st_##mod[PAST], &s_st_##mod[CURR], (size));	\
-		memset(&s_st_##mod[CURR], '\0', (size));		\
-	}while(0)
+#define myalloc(p, type, size)                  \
+    struct type * p = NULL;                 \
+p = (struct type *)malloc(size);            \
+if(!p) {                        \
+    fprintf(stderr, "failed to alloc memory\n");    \
+    exit(EXIT_FAILURE);             \
+}                           \
+memset(p, 0, size)                  \
+
+#define BUFFER_ROTATE(mod, size)                    \
+    do {                                \
+        memcpy(&s_st_##mod[PAST], &s_st_##mod[CURR], (size));   \
+        memset(&s_st_##mod[CURR], '\0', (size));        \
+    }while(0)
 
 inline void func_mod_free(struct module *mod)
 {
-	free(mod->detail);
-	free(mod->summary);
-	mod->detail = NULL;
-	mod->summary = NULL;
+    free(mod->detail);
+    free(mod->summary);
+    mod->detail = NULL;
+    mod->summary = NULL;
 }
 
-#define INIT_STRING_P(s, nr, len)				\
-	do {							\
-		int i;						\
-		s = (char **)malloc((nr) * sizeof(char *));	\
-		for(i = 0; i < (nr); i++)			\
-		s[i] = (char *)malloc(len);		\
-	} while(0)
-
-
-#define DECLARE_TMP_MOD_STATISTICS(mod)		\
-	union mod##_statistics mod##_tmp_s;	\
-
-#define SET_CURRENT_VALUE(mod, type, member, ret)	\
-	do {						\
-		mod##_tmp_s.mod##_##type.ret =		\
-		s_st_##mod[CURR].member;	\
-	}while(0)
-
-#define __COMPUTE_MOD_VALUE(ret, ops, m1, m2, i)	\
-	do {						\
-		if (!(i)) {				\
-			(ret) = 0;			\
-		}					\
-		else if ((m1) == (m2))	{		\
-			(ret) = 0;			\
-		}					\
-		else {					\
-			(ret) = ops((m1), (m2), (i));	\
-		}					\
-	} while(0)
-
-
-#define COMPUTE_MOD_VALUE(mod, ops, type, member, i, ret)		\
-	do {								\
-		/*printf("i = %ld\n", (i));*/				\
-		__COMPUTE_MOD_VALUE(					\
-				mod##_tmp_s.mod##_##type.ret,	\
-				ops,				\
-				s_st_##mod[1].member,		\
-				s_st_##mod[0].member,		\
-				(i));				\
-	} while(0)
+#define INIT_STRING_P(s, nr, len)               \
+    do {                            \
+        int i;                      \
+        s = (char **)malloc((nr) * sizeof(char *)); \
+        for(i = 0; i < (nr); i++)           \
+        s[i] = (char *)malloc(len);     \
+    } while(0)
+
+
+#define DECLARE_TMP_MOD_STATISTICS(mod)     \
+    union mod##_statistics mod##_tmp_s; \
+
+#define SET_CURRENT_VALUE(mod, type, member, ret)   \
+    do {                        \
+        mod##_tmp_s.mod##_##type.ret =      \
+        s_st_##mod[CURR].member;    \
+    }while(0)
+
+#define __COMPUTE_MOD_VALUE(ret, ops, m1, m2, i)    \
+    do {                        \
+        if (!(i)) {             \
+            (ret) = 0;          \
+        }                   \
+        else if ((m1) == (m2))  {       \
+            (ret) = 0;          \
+        }                   \
+        else {                  \
+            (ret) = ops((m1), (m2), (i));   \
+        }                   \
+    } while(0)
+
+
+#define COMPUTE_MOD_VALUE(mod, ops, type, member, i, ret)       \
+    do {                                \
+        /*printf("i = %ld\n", (i));*/               \
+        __COMPUTE_MOD_VALUE(                    \
+                mod##_tmp_s.mod##_##type.ret,   \
+                ops,                \
+                s_st_##mod[1].member,       \
+                s_st_##mod[0].member,       \
+                (i));               \
+    } while(0)
 
 
 /* Fix me */
-#define __SET_MOD_STATISTICS(val, mean, max, min, i)		\
-	do{							\
-		static int sw = 0;				\
-		if(!sw) {					\
-			(max) = (val);				\
-			(min) = (val);				\
-			sw = 1;					\
-		} else {					\
-			if (((val) - (max)) > 0.00001)		\
-			(max) = (val);			\
-			else if (((min) - (val)) > 0.00001) {	\
-				(min) = (val);			\
-			}					\
-		}						\
-		(mean) += (val);				\
-	} while(0)
-
-#define SET_MOD_STATISTICS(mod, member, i, type)	\
-	__SET_MOD_STATISTICS				\
-(						\
-						mod##_tmp_s.mod##_##type.member,		\
-						mod##_statis[MEAN].mod##_##type.member,	\
-						mod##_statis[MAX].mod##_##type.member,		\
-						mod##_statis[MIN].mod##_##type.member,		\
-						i)
-
-#define __PRINT_AVG(buf, pos, val, member, idx, count, otype) do	\
-{							\
-	if ((idx) == MEAN)				\
-	val[(idx)].member =			\
-	val[(idx)].member / (count);	\
-	PRINT(buf[(idx)] + pos[(idx)],			\
-			val[(idx)].member,			\
-			pos[(idx)], (otype));			\
+#define __SET_MOD_STATISTICS(val, mean, max, min, i)        \
+    do{                         \
+        static int sw = 0;              \
+        if(!sw) {                   \
+            (max) = (val);              \
+            (min) = (val);              \
+            sw = 1;                 \
+        } else {                    \
+            if (((val) - (max)) > 0.00001)      \
+            (max) = (val);          \
+            else if (((min) - (val)) > 0.00001) {   \
+                (min) = (val);          \
+            }                   \
+        }                       \
+        (mean) += (val);                \
+    } while(0)
+
+#define SET_MOD_STATISTICS(mod, member, i, type)    \
+    __SET_MOD_STATISTICS                \
+(                       \
+                        mod##_tmp_s.mod##_##type.member,        \
+                        mod##_statis[MEAN].mod##_##type.member, \
+                        mod##_statis[MAX].mod##_##type.member,      \
+                        mod##_statis[MIN].mod##_##type.member,      \
+                        i)
+
+#define __PRINT_AVG(buf, pos, val, member, idx, count, otype) do    \
+{                           \
+    if ((idx) == MEAN)              \
+    val[(idx)].member =         \
+    val[(idx)].member / (count);    \
+    PRINT(buf[(idx)] + pos[(idx)],          \
+            val[(idx)].member,          \
+            pos[(idx)], (otype));           \
 }while(0)
 
 #define __PRINT_AVG_SEP(buf, pos, val, member, sep, idx, count, otype) do \
-{							\
-	if((idx) == MEAN)				\
-	val[(idx)].member =			\
-	(val[(idx)].member / (count));	\
-	PRINT(buf[(idx)] + pos[(idx)],			\
-			val[(idx)].member * (sep),		\
-			pos[(idx)], (otype));			\
+{                           \
+    if((idx) == MEAN)               \
+    val[(idx)].member =         \
+    (val[(idx)].member / (count));  \
+    PRINT(buf[(idx)] + pos[(idx)],          \
+            val[(idx)].member * (sep),      \
+            pos[(idx)], (otype));           \
 }while(0)
 
-inline char *getitem(char *r, char *mnt) 
+inline char *getitem(char *r, char *mnt)
 {
-	char *start, *end;
-	if (r == NULL || *r == '\0') {
-		return NULL;
-	}else  {
-		start = strstr(r, "=");
-		end = strstr(r, ";");
-		memcpy(mnt, start + 1, end - start -1);
-		r = end + 1;
-		mnt[end - start - 1] = '\0';
-	}
-
-	return r;
+    char *start, *end;
+    if (r == NULL || *r == '\0') {
+        return NULL;
+    } else {
+        start = strstr(r, "=");
+        end = strstr(r, ";");
+        memcpy(mnt, start + 1, end - start -1);
+        r = end + 1;
+        mnt[end - start - 1] = '\0';
+    }
+
+    return r;
 }
 
 #define CALITV(pt, ct, i) ((i) = ((pt) < (ct)) ? (ct) - (pt) : 1)
 
+
 #endif
diff --git a/include/tsar.h b/include/tsar.h
index 55af424..21cd92b 100644
--- a/include/tsar.h
+++ b/include/tsar.h
@@ -1,3 +1,4 @@
+
 /*
  * (C) 2010-2011 Alibaba Group Holding Limited
  *
@@ -15,8 +16,10 @@
  *
  */
 
-#ifndef _TSAR_H
-#define _TSAR_H
+
+#ifndef TSAR_H
+#define TSAR_H
+
 
 #include <string.h>
 #include <unistd.h>
@@ -30,6 +33,10 @@
 #include <getopt.h>
 #include <ctype.h>
 #include <sys/stat.h>
+#include <luajit-2.0/lua.h>
+#include <luajit-2.0/lauxlib.h>
+#include <luajit-2.0/lualib.h>
+
 
 #include "framework.h"
 #include "debug.h"
@@ -38,18 +45,22 @@
 #include "output_file.h"
 #include "output_print.h"
 #include "output_db.h"
+#include "output_tcp.h"
 #include "output_nagios.h"
 #include "common.h"
+#include "tsar_lua_util.h"
+
 
-struct statistic
-{
-	int	total_mod_num;
-	time_t	cur_time;
+struct statistic {
+    int    total_mod_num;
+    time_t cur_time;
 };
 
 
 extern struct configure conf;
-extern struct module	mods[MAX_MOD_NUM];
+extern struct module    *mods[MAX_MOD_NUM];
 extern struct statistic statis;
+extern lua_State *L;
+
 
 #endif
diff --git a/include/tsar_lua_util.h b/include/tsar_lua_util.h
new file mode 100644
index 0000000..54416e6
--- /dev/null
+++ b/include/tsar_lua_util.h
@@ -0,0 +1,29 @@
+
+/*
+ * (C) 2010-2011 Alibaba Group Holding Limited
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+
+#ifndef TSAR_LUA_UTIL_H
+#define TSAR_LUA_UTIL_H
+
+
+#include "define.h"
+
+void close_luavm(lua_State *L);
+lua_State *load_luavm();
+
+#endif
diff --git a/info.md b/info.md
new file mode 100644
index 0000000..26760ee
--- /dev/null
+++ b/info.md
@@ -0,0 +1,536 @@
+## 系统模块
+### cpu
+#### 字段含义
+* user:  表示CPU执行用户进程的时间,通常期望用户空间CPU越高越好.
+* sys:   表示CPU在内核运行时间,系统CPU占用率高,表明系统某部分存在瓶颈.通常值越低越好.
+* wait:  CPU在等待I/O操作完成所花费的时间.系统部应该花费大量时间来等待I/O操作,否则就说明I/O存在瓶颈.
+* hirq: 系统处理硬中断所花费的时间百分比
+* sirq: 系统处理软中断所花费的时间百分比
+* util: CPU总使用的时间百分比
+* nice:  系统调整进程优先级所花费的时间百分比
+* steal: 被强制等待（involuntary wait）虚拟CPU的时间,此时hypervisor在为另一个虚拟处理器服务
+* ncpu:  CPU的总个数
+
+#### 采集方式
+CPU的占用率计算,都是根据/proc/stat计数器文件而来,stat文件的内容基本格式是:
+
+    cpu  67793686 1353560 66172807 4167536491 2705057 0 195975 609768
+    cpu0 10529517 944309 11652564 835725059 2150687 0 74605 196726
+    cpu1 14380773 127146 13908869 832565666 150815 0 31780 108418
+
+cpu是总的信息,cpu0,cpu1等是各个具体cpu的信息,共有8个值,单位是ticks,分别是：
+- User time, 67793686
+- Nice time, 1353560
+- System time, 66172807
+- Idle time, 4167536491
+- Waiting time, 2705057
+- Hard Irq time, 0
+- SoftIRQ time, 195975
+- Steal time, 609768
+
+`CPU总时间=user+system+nice+idle+iowait+irq+softirq+Stl`
+
+各个状态的占用=状态的cpu时间/CPU总时间＊100%
+
+比较特殊的是CPU总使用率的计算(util),目前的算法是:
+`util = 1 - idle - iowait - steal` 。
+
+### mem
+#### 字段含义
+* free:   空闲的物理内存的大小
+* used:   已经使用的内存大小
+* buff:   buff使用的内存大小,buffer is something that has yet to be "written" to disk.
+* cach:   操作系统会把经常访问的东西放在cache中加快执行速度,A cache is something that has been "read" from the disk and stored for later use
+* total:  系统总的内存大小
+* util:   内存使用率
+
+#### 采集方法
+内存的计数器在/proc/meminfo,里面有一些关键项
+
+        MemTotal:      7680000 kB
+        MemFree:        815652 kB
+        Buffers:       1004824 kB
+        Cached:        4922556 kB
+
+含义就不解释了,主要介绍一下内存使用率的计算算法:
+`util = (total - free - buff - cache) / total * 100%`
+
+### load
+#### 字段含义
+* load1: 一分钟的系统平均负载
+* load5: 五分钟的系统平均负载
+* load15:十五分钟的系统平均负载
+* runq:  在采样时刻,运行队列的任务的数目,与/proc/stat的procs_running表示相同意思
+* plit:  在采样时刻,系统中活跃的任务的个数（不包括运行已经结束的任务）
+
+#### 采集方法
+/proc/loadavg文件中保存的有负载相关的数据：
+
+`0.00 0.01 0.00 1/271 23741`
+
+分别是1分钟负载,五分钟负载,十五分钟负载,运行进程／总进程 最大的pid
+
+只需要采集前五个数据既可得到所有信息
+
+注意:只有当系统负载除cpu核数>1的时候,系统负载较高
+
+### traffic
+#### 字段含义
+* bytin:   入口流量byte/s
+* bytout:  出口流量byte/s
+* pktin:   入口pkt/s
+* pktout:  出口pkt/s
+
+#### 采集方法
+流量的计数器信息来自:/proc/net/dev
+
+        face |bytes    packets errs drop fifo frame compressed multicast|bytes    packets errs drop fifo colls carrier compressed
+        lo:1291647853895 811582000    0    0    0     0          0         0 1291647853895 811582000    0    0    0     0       0          0
+        eth0:853633725380 1122575617    0    0    0     0          0         0 1254282827126 808083790    0    0    0     0       0          0
+
+字段的含义第一行已经标示出来,每一行代表一个网卡,tsar主要采集的是出口和入口的bytes／packets。
+
+注意tsar只对以eth和em开头的网卡数据进行了采集,像lo这种网卡直接就忽略掉了,流量的单位是byte。
+
+### tcp
+#### 字段含义
+* active:主动打开的tcp连接数目
+* pasive:被动打开的tcp连接数目
+* iseg:  收到的tcp报文数目
+* outseg:发出的tcp报文数目
+* EstRes:Number of resets that have occurred at ESTABLISHED
+* AtmpFa:Number of failed connection attempts
+* CurrEs:当前状态为ESTABLISHED的tcp连接数
+* retran:系统的重传率
+
+#### 采集方法
+tcp的相关计数器文件是:/proc/net/snmp
+
+        Tcp: RtoAlgorithm RtoMin RtoMax MaxConn ActiveOpens PassiveOpens AttemptFails EstabResets CurrEstab InSegs OutSegs RetransSegs InErrs OutRsts
+        Tcp: 1 200 120000 -1 31702170 14416937 935062 772446 16 1846056224 1426620266 448823 0 5387732
+
+我们主要关注其中的ActiveOpens/PassiveOpens/AttemptFails/EstabResets/CurrEstab/InSegs/OutSegs/RetransSegs
+
+主要关注一下重传率的计算方式:
+`retran = (RetransSegs－last RetransSegs) ／ (OutSegs－last OutSegs) * 100%`
+
+### udp
+#### 字段含义
+* idgm:  收到的udp报文数目
+* odgm:  发送的udp报文数目
+* noport:udp协议层接收到目的地址或目的端口不存在的数据包
+* idmerr:udp层接收到的无效数据包的个数
+
+
+#### 采集方法
+UDP的数据来源文件和TCP一样,也是在/proc/net/snmp
+
+        Udp: InDatagrams NoPorts InErrors OutDatagrams
+        Udp: 31609577 10708119 0 159885874
+
+### io
+#### 字段含义
+* rrqms: The number of read requests merged per second that were issued to the device.
+* wrqms: The number of write requests merged per second that were issued to the device.
+* %rrqm: The percentage of read requests merged together before being sent to the device.
+* %wrqm: The percentage of write requests merged together before being sent to the device.
+* rs:    The number of read requests that were issued to the device per second.
+* ws:    The number of write requests that were issued to the device per second.
+* rsecs: The number of sectors read from the device per second.
+* wsecs: The number of sectors written to the device per second.
+* rqsize:The average size (in megabytes) of the requests that were issued to the device.
+* rarqsz:The average size (in megabytes) of the read requests that were issued to the device.
+* warqsz:The average size (in megabytes) of the write requests that were issued to the device.
+* qusize:The average queue length of the requests that were issued to the device.
+* await: The average time (in milliseconds) for I/O requests issued to the device to be served. This includes the time spent by the requests in queue and the time spent servicing them.
+* rawait:The average time (in milliseconds) for read requests issued to the device to be served. This includes the time spent by the requests in queue and the time spent servicing them.
+* wawait:The average time (in milliseconds) for write requests issued to the device to be served. This includes the time spent by the requests in queue and the time spent servicing them.
+* svctm: The average service time (in milliseconds) for I/O requests that were issued to the device.
+* util:  Percentage of CPU time during which I/O requests were issued to the device (bandwidth utilization for the device).Device saturation occurs when this value is close to 100%.
+
+#### 采集方法
+IO的计数器文件是:/proc/diskstats,比如:
+
+        202    0 xvda 12645385 1235409 416827071 59607552 193111576 258112651 3679534806 657719704 0 37341324 717325100
+        202    1 xvda1 421 2203 3081 9888 155 63 421 1404 0 2608 11292
+
+每一行字段的含义是:
+* major:     主设备号
+* minor:      次设备号,设备号是用来区分磁盘的类型和厂家信息
+* name:       设备名称
+* rd_ios:     读完成次数,number of issued reads. This is the total number of reads completed successfully
+* rd_merges:  合并读完成次数,为了效率可能会合并相邻的读和写.从而两次4K的读在它最终被处理到磁盘上之前可能会变成一次8K的读,才被计数（和排队）,因此只有一次I/O操作
+* rd_sectors: 读扇区的次数,number of sectors read. This is the total number of sectors read successfully.
+* rd_ticks:   读花费的毫秒数,number of milliseconds spent reading. This is the total number of milliseconds spent by all reads
+* wr_ios:     写完成次数,number of writes completed. This is the total number of writes completed successfully
+* wr_merges:  合并写完成次数,number of writes merged Reads and writes which are adjacent to each other may be merged for efficiency. Thus two 4K reads may become one 8K read before it is ultimately handed to the disk, and so it will be counted (and queued) as only one I/O.
+* wr_sectors: 写扇区次数,number of sectors written. This is the total number of sectors written successfully
+* wr_ticks:   写花费的毫秒数,number of milliseconds spent writing. This is the total number of milliseconds spent by all writes.
+* cur_ios:    正在处理的输入/输出请求数,number of I/Os currently in progress. The only field that should go to zero. Incremented as requests are given to appropriate request_queue_t and decremented as they finish.
+* ticks:      输入/输出操作花费的毫秒数
+* aveq:       输入/输出操作花费的加权毫秒数
+
+通过这些计数器可以算出来上面的每个字段的值
+
+    double n_ios = rd_ios + wr_ios;
+    st_array[0] = rd_merges / (inter * 1.0);
+    st_array[1] = wr_merges / (inter * 1.0);
+    st_array[2] = rd_merges + rd_ios ? (double)rd_merges / (rd_merges + rd_ios) * 100 : 0.0;
+    st_array[3] = wr_merges + wr_ios ? (double)wr_merges / (wr_merges + wr_ios) * 100 : 0.0;
+    st_array[4] = rd_ios / (inter * 1.0);
+    st_array[5] = wr_ios / (inter * 1.0);
+    st_array[6] = rd_sectors / (inter * 1.0);
+    st_array[7] = wr_sectors / (inter * 1.0);
+    st_array[8] = n_ios ? (rd_sectors + wr_sectors) / (n_ios * 2) : 0.0;
+    st_array[9] = rd_ios ? rd_sectors / ((double)rd_ios * 2) : 0.0;
+    st_array[10] = wr_ios ? wr_sectors / ((double)wr_ios * 2) : 0.0;
+    st_array[11] = aveq / (inter * 1000);
+    st_array[12] = n_ios ? (rd_ticks + wr_ticks) / (double)n_ios : 0.0;
+    st_array[13] = rd_ios ? rd_ticks / (double)rd_ios : 0.0;
+    st_array[14] = wr_ios ? wr_ticks / (double)wr_ios : 0.0;
+    st_array[15] = n_ios ? ticks / n_ios : 0.0;
+    st_array[16] = ticks / (inter * 10.0); /* percentage! */
+    /*st_array分别代表tsar显示的每一个值*/
+
+注意:
+> 1. 扇区一般都是512字节,因此有的地方除以2了
+> 1. ws是指真正落到io设备上的写次数, wrqpms是指系统调用合并的写次数, 它们之间的大小关系没有可比性,因为不知道多少请求能够被合并,比如发起了100个read系统调用,每个读4K,假如这100个都是连续的读,由于硬盘通常允许最大的request为256KB,那么block层会把这100个读请求合并成2个request,一个256KB,另一个144KB,rrqpm/s为100,因为100个request都发生了合并,不管它最后合并成几个；r/s为2,因为最后的request数为2
+
+### partition
+#### 字段含义
+* bfree: 分区空闲的字节
+* bused: 分区使用中的字节
+* btotl: 分区总的大小
+* util:  分区使用率
+* ifree: 可用文件结点数
+* itotl: 文件结点总数
+* iutil: 文件结点使用率
+
+#### 采集方法
+首先通过/etc/mtab获取到分区信息,然后通过statfs访问该分区的信息,查询文件系统相关信息,包含:
+
+        struct statfs {
+        long f_type; /* 文件系统类型 */
+        long f_bsiz
+        e; /* 经过优化的传输块大小 */
+        long f_blocks; /* 文件系统数据块总数 */
+        long f_bfree; /* 可用块数 */
+        long f_bavail; /* 非超级用户可获取的块数 */
+        long f_files; /* 文件结点总数 */
+        long f_ffree; /* 可用文件结点数 */
+        fsid_t f_fsid; /* 文件系统标识 */
+        long f_namelen; /* 文件名的最大长度 */
+        };
+
+然后就可以计算出tsar需要的信息,分区的字节数＝块数＊块大小＝f_blocks * f_bsize
+
+### pcsw
+#### 字段含义
+* cswch: 进程切换次数
+* proc:   新建的进程数
+
+#### 采集方法
+计数器在/proc/stat:
+
+        ctxt 19873315174
+        processes 296444211
+
+分别代表进程切换次数,以及进程数
+
+### tcpx
+#### 字段含义
+recvq sendq est twait fwait1 fwait2 lisq lising lisove cnest ndrop edrop rdrop pdrop kdrop
+
+分别代表
+
+tcprecvq tcpsendq tcpest tcptimewait tcpfinwait1 tcpfinwait2 tcplistenq tcplistenincq tcplistenover tcpnconnest tcpnconndrop tcpembdrop tcprexmitdrop tcppersistdrop tcpkadrop
+#### 采集方法
+计数器来自:/proc/net/netstat /proc/net/snmp
+
+里面用到的数据有:
+
+        TcpExt: SyncookiesSent SyncookiesRecv SyncookiesFailed EmbryonicRsts PruneCalled RcvPruned OfoPruned OutOfWindowIcmps LockDroppedIcmps ArpFilter TW TWRecycled TWKilled PAWSPassive PAWSActive PAWSEstab DelayedACKs DelayedACKLocked DelayedACKLost ListenOverflows ListenDrops TCPPrequeued TCPDirectCopyFromBacklog TCPDirectCopyFromPrequeue TCPPrequeueDropped TCPHPHits TCPHPHitsToUser TCPPureAcks TCPHPAcks TCPRenoRecovery TCPSackRecovery TCPSACKReneging TCPFACKReorder TCPSACKReorder TCPRenoReorder TCPTSReorder TCPFullUndo TCPPartialUndo TCPDSACKUndo TCPLossUndo TCPLoss TCPLostRetransmit TCPRenoFailures TCPSackFailures TCPLossFailures TCPFastRetrans TCPForwardRetrans TCPSlowStartRetrans TCPTimeouts TCPRenoRecoveryFail TCPSackRecoveryFail TCPSchedulerFailed TCPRcvCollapsed TCPDSACKOldSent TCPDSACKOfoSent TCPDSACKRecv TCPDSACKOfoRecv TCPAbortOnSyn TCPAbortOnData TCPAbortOnClose TCPAbortOnMemory TCPAbortOnTimeout TCPAbortOnLinger TCPAbortFailed TCPMemoryPressures
+        TcpExt: 0 0 0 80 539 0 0 0 0 0 3733709 51268 0 0 0 80 5583301 5966 104803 146887 146887 6500405 39465075 2562794034 0 689613557 2730596 540646233 234702206 0 44187 2066 94 240 0 114 293 1781 7221 60514 185158 2 2 3403 400 107505 5860 24813 174014 0 2966 7 168787 106151 40 32851 2 0 2180 9862 0 15999 0 0 0
+
+具体字段找到并且获取即可
+
+### percpu ncpu
+#### 字段含义
+字段含义等同cpu模块,只不过能够支持采集具体的每一个cpu的信息
+#### 采集方法
+等同于cpu模块
+
+### pernic
+#### 字段含义
+字段含义等同traffic模块,只不过能够支持采集具体的每一个网卡的信息
+#### 采集方法
+等同于traffic模块
+
+## 应用模块
+### proc
+#### 字段含义
+* user: 某个进程用户态cpu消耗
+* sys:  某个进程系统态cpu消耗
+* total:某个进程总的cpu消耗
+* mem:  某个进程的内存消耗百分比
+* RSS:  某个进程的虚拟内存消耗,这是驻留在物理内存的一部分.它没有交换到硬盘.它包括代码,数据和栈
+* read: 进程io读字节
+* write:进程的io写字节
+
+### #采集方法
+计数器文件
+> /proc/pid/stat:获取进程的cpu信息
+> /proc/pid/status:获取进程的mem信息
+> /proc/pid/io:获取进程的读写IO信息
+
+注意,需要将采集的进程名称配置在/etc/tsar/tsar.conf总的mod_proc on procname,这样就会找到procname的pid,并进行数据采集
+
+### nginx
+#### 字段含义
+* accept:总共接收的新连接数目
+* handle:总共处理的连接数目
+* reqs:总共产生请求数目
+* active:活跃的连接数,等于read+write+wait
+* read:读取请求数据的连接数目
+* write:向用户写响应数据的连接数目
+* wait:长连接等待的连接数目
+* qps:每秒处理的请求数
+* rt:平均响应时间ms
+* sslqps:每秒处理的SSL请求数
+* spdyps:每秒处理的spdy请求数
+* sslhst:平均ssl握手时间ms
+
+
+#### 采集方法
+通过nginx的采集模块配置,访问特定地址,具体参见:https://github.com/taobao/tsar-mod_nginx
+
+        location = /nginx_status {
+            stub_status on;
+        }
+
+请确保如下方式能得到数据：
+curl 127.0.0.1:80/nginx_status  -H 'Host: status.taobao.com'
+请求到的数据是:
+
+        Active connections: 1
+        server accepts handled requests request_time
+         24 24 7 0
+        Reading: 0 Writing: 1 Waiting: 0
+        SSL: 0 SPDY: 0
+（注：对于上述返回数据中的server accepts handled requests request_time，当前是通过“ 24 24 7 0”数据行首的空格作为前导。现tsar在本模块中同时支持“Server accepts: 24 handled: 24 requests: 7 request_time 0”格式返回该数据行。今后将升级tengine改用此方式。）
+
+需要确保nginx配置该location,并且能够访问`curl http://localhost/nginx_status`得到上面的数据  
+如果nginx的端口不是80,则需要在配置文件中指定端口,配置文件是/etc/tsar/tsar.conf,修改mod_nginx on为mod_nginx on 8080 。
+
+不同端口的nginx数据以不同item的形式展现，在对各item进行合并的时候（-m），除rt以及sslhst依然为平均值之外，其他的所有值都为所有端口的值的总和
+
+类似的有nginx_code, nginx_domain模块,相应的配置是:
+
+        req_status_zone server "$host" 20M;
+        req_status server;
+        location /traffic_status {
+                req_status_show;
+        }
+
+通过访问`curl http://localhost/traffic_status`能够得到如下字段的数据
+`localhost,0,0,2,2,2,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0`
+
+请求到的数据每个字段的含义是:
+* kv 计算得到的req_status_zone指令定义变量的值,此时为domain字段
+* bytes_in_total 从客户端接收流量总和
+* bytes_out_total 发送到客户端流量总和
+* conn_total 处理过的连接总数
+* req_total 处理过的总请求数
+* 2xx 2xx请求的总数
+* 3xx 3xx请求的总数
+* 4xx 4xx请求的总数
+* 5xx 5xx请求的总数
+* other 其他请求的总数
+* rt_total rt的总数
+* upstream_req 需要访问upstream的请求总数
+* upstream_rt 访问upstream的总rt
+* upstream_tries upstram总访问次数
+* 200 200请求的总数
+* 206 206请求的总数
+* 302 302请求的总数
+* 304 304请求的总数
+* 403 403请求的总数
+* 404 404请求的总数
+* 416 416请求的总数
+* 499 499请求的总数
+* 500 500请求的总数
+* 502 502请求的总数
+* 503 503请求的总数
+* 504 504请求的总数
+* 508 508请求的总数
+* detail_other 非以上13种status code的请求总数
+
+如果domain数量太多,或者端口不是80,需要进行专门的配置,配置文件内容如下:
+
+        port=8080 #指定nginx的端口
+        top=10 #指定最多采集的域名个数，按照请求总个数排列
+        domain=a.com b.com #指定特定需要采集的域名列表,分隔符为空格,逗号,或者制表符
+
+在/etc/tsar/tsar.conf中指定配置文件的路径:mod_nginx_domain on /tmp/my.conf
+
+#### nginx_domain_traffic
+nginx配置是:
+
+        req_status_zone server "$host" 20M;
+        req_status server;
+
+        # req_status_zone_add_indecator 指令：可以在req status输出的每一行最后添加新的字段
+        # 这里添加的字段用于统计nginx的变量: $2xx_bytes_sent, $3xx_bytes_sent, $4xx_bytes_sent, $5xx_bytes_sent
+        # $2xx_bytes_sent: 请求返回2xx时候，发送给客户端的数据量(如果请求非2xx则该变量为0)
+        req_status_zone_add_indecator server $2xx_bytes_sent $3xx_bytes_sent $4xx_bytes_sent $5xx_bytes_sent;
+
+        location /traffic_status {
+                req_status_show;
+        }
+
+输出实例:
+
+       module004033.sqa.cm4 tsar $ tsar --nginx_domain_traffic -li1
+       Time              -----------------localhost:8080----------------- ----------------www.foo.com:8080----------------
+       Time               bytin  bytout  2XXout  3XXout  4XXout  5XXout    bytin  bytout  2XXout  3XXout  4XXout  5XXout
+       09/01/15-13:45:48   0.00    0.00    0.00    0.00    0.00    0.00   410.1K   16.6M   16.6M    0.00    0.00    0.00
+       09/01/15-13:45:49   0.00    0.00    0.00    0.00    0.00    0.00   407.8K   16.5M   16.5M    0.00    0.00    0.00
+       09/01/15-13:45:51 159.0K  287.4K    0.00    0.00    0.00  287.4K   258.6K   10.5M   10.5M    0.00    0.00    0.00
+       09/01/15-13:45:52 245.5K  443.5K    0.00    0.00    0.00  443.5K   224.2K    9.1M    9.1M    0.00    0.00    0.00
+
+字段含义:
+* bytin:   收到的请求字节数byte/s
+* bytout:  输出的应答字节数byte/s
+* 2XXout:  输出的2XX应答字节数byte/s
+* 3XXout:  输出的3XX应答字节数byte/s
+* 4XXout:  输出的4XX应答字节数byte/s
+* 5XXout:  输出的5XX应答字节数byte/s
+
+#### nginx_ups
+用于输出nginx upstream想关信息
+nginx配置是:
+
+        req_status_zone server "$host" 20M;
+        req_status server;
+        req_status_zone_add_indecator server $response_fbt_time $upstream_response_fbt_time $upstream_response_length;
+
+        location /traffic_status {
+                req_status_show;
+        }
+
+输出实例:
+
+         module004033.sqa.cm4 tsar $ tsar --nginx_ups -li1
+         Time              ----------------------------nginx_ups---------------------------
+         Time               traff     qps     4XX     5XX    rqps      rt     fbt    ufbt
+         09/01/15-16:26:29  15.8M    3.9K    3.9K    0.00    0.00    9.7K    9.7K    9.7K
+         09/01/15-16:26:30  15.8M    3.9K    3.9K    0.00    0.00    9.7K    9.7K    9.7K
+         09/01/15-16:26:31   4.9M    1.2K    1.2K    0.00    0.00    3.0K    3.0K    3.0K
+
+字段含义:
+* traff: 后端返回的应答body的流量(不包括http应答头部)
+* qps:   后端qps
+* rqps:  后端总qps(包含重试的qps + 后端qps)
+* 4XX:   后端返回4XX状态码的qps
+* 5XX:   后端返回5XX状态码的qps
+* rt:    后端应答时间
+* fbt:   tengine首字节时间
+* ufbt:  后端应答首字节时间
+
+### nginx_live
+#### 字段含义
+* online:当前总共在线数
+* olhstr:历史总共在线数
+* olvary:历史在线数增长量（待商榷，不显示）
+* upflow:上行总流量
+* uspeed:上行总速度
+* downfl:下行总流量
+* dspeed:下行总速度
+* fmtime:当前平均首播时间
+* fmdata:不显示
+* dropfr:丢帧
+
+
+#### 采集方法
+请确保如下方式能得到数据：
+curl -x 127.0.0.1:7001 http://status.taobao.com/rtmp_reqstat
+请求到的数据是:
+rtmp://pagefault/alicdn/diaoliang123,fm_time:574 drop_frame:0 online:1 online_history:2 down_flow:166096189 up_flow:166096188 internal:0 edge:2
+
+### squid
+#### 字段含义
+* qps:   每秒请求数
+* rt:    访问平均相应时间
+* r_hit: 请求命中率
+* b_hit: 字节命中率
+* d_hit: 磁盘命中率
+* m_hit: 内存命中率
+* fdused: Number of file desc currently in use
+* fdque:  Files queued for open
+* objs:   StoreEntries
+* inmem:  StoreEntries with MemObjects
+* hot:    Hot Object Cache Items
+* size:   Mean Object Size
+
+####采集方法
+访问squid的mgrinfo信息获取,有些字段经过了一些patch,可能不适用外部版本
+
+###haproxy
+####字段含义
+* stat:   状态,1正常
+* uptime:启动持续时间
+* conns: 总的连接数
+* qps:   每秒请求数
+* hit:   haproxy开启cache时的命中率
+* rt:    平均响应时间ms
+
+#### 采集方法
+haproxy经过了patch,能够在多进程模式下进行统计信息的汇总,然后通过haproxy的本地访问其状态页面admin分析得到
+
+### lvs
+#### 字段含义
+* stat:   lvs状态,1正常
+* conns: 总的连接数
+* pktin: 收到的包数
+* pktout:发出的包数
+* bytin: 收到的字节数
+* bytout:发出的字节数
+* total: lvs所有的 session 数量, 包含 local 和 sync
+* local: lvs本机转发的 session 数量
+* lact: local session 中处于 establish 状态的数量
+* linact: local session 中处于非 establish 状态的数量
+* sync: 其他lvs同步过来的 session 数量
+* sact: sync session 中处于 establish 状态的数量
+* sinact: sync session 中处于非 establish 状态的数量
+* templ: 会话保持(模板) session 的数量
+
+
+#### 采集方法
+内核版 lvs: 访问lvs的统计文件:/proc/net/ip_vs_stats, /proc/net/ip_vs_conn_stats
+netframe lvs: 访问 lvs 的命令行工具: slb_admin -ln --total --dump, appctl -cas
+
+### apache
+参见:https://github.com/kongjian/tsar-apache
+### tcprt
+私有应用,略
+### swift
+私有应用,略
+### cgcpu/cgmem/cgblkio
+私有应用,略
+### trafficserver
+待补充
+### tmd
+私有应用,略
+
+### lua
+#### 采集方法
+在/etc/tsar/tsar.conf中：
+
+        mod_lua on {lua_file_name}
+
+启用lua模块，将从绝对路径调用{lua_file_name}这个lua脚本文件。
+
+mod_lua 依赖luajit-5.1。
+
+目前为仅有一个tsar模块支持lua，通过修改lua脚本文件来实现不同的数据采集。目前支持11个字段供lua操作
+具体实现样例见lua_modules/nginx_mem.lua，该脚本实现采集本机上所有nginx进程分配的内存总数。
diff --git a/luadevel/Makefile.test b/luadevel/Makefile.test
new file mode 100644
index 0000000..8930fe5
--- /dev/null
+++ b/luadevel/Makefile.test
@@ -0,0 +1,8 @@
+install:
+	mkdir -p /etc/tsar/conf.d/
+	cp ./mod_test.lua /usr/local/tsar/modules/
+	cp ./mod_test.conf /etc/tsar/conf.d/test.conf
+
+uninstall:
+	rm /usr/local/tsar/modules/mod_test.lua
+	rm /etc/tsar/conf.d/test.conf
diff --git a/luadevel/mod_lua_test.conf b/luadevel/mod_lua_test.conf
new file mode 100644
index 0000000..b3069ab
--- /dev/null
+++ b/luadevel/mod_lua_test.conf
@@ -0,0 +1,15 @@
+mod_test on
+
+####add it to tsar default output
+output_stdio_mod mod_test
+
+####add it to center db
+#output_db_mod mod_test
+
+####add it to nagios send
+####set nagios threshold for alert
+#output_nagios_mod mod_test
+
+#threshold test.value1;N;N;N;N;
+#threshold test.value2;N;N;N;N;
+#threshold test.value3;N;N;N;N;
diff --git a/luadevel/mod_lua_test.lua b/luadevel/mod_lua_test.lua
new file mode 100644
index 0000000..a9b943b
--- /dev/null
+++ b/luadevel/mod_lua_test.lua
@@ -0,0 +1,51 @@
+local _M = {
+    _VERSION = "0.1.0"
+}
+
+local cjson = require("cjson")
+local socket = require("socket")
+local http = require("socket.http")
+local ltn12 = require("ltn12")
+local DETAIL_BIT = tsar.DETAIL_BIT
+local SUMMARY_BIT = tsar.SUMMARY_BIT
+local HIDE_BIT = tsar.HIDE_BIT
+local STATS_NULL = tsar.STATS_NULL
+local string_format = string.format
+
+local info = {
+    {hdr = " value1", summary_bit = SUMMARY_BIT, merge_mode = 0, stats_opt = STATS_NULL},
+    {hdr = " value2", summary_bit = DETAIL_BIT, merge_mode = 0, stats_opt = STATS_NULL},
+    {hdr = " value3", summary_bit = DETAIL_BIT, merge_mode = 0, stats_opt = STATS_NULL},
+}
+
+local value1 = 1
+local value2 = 2
+local value3 = 3
+function _M.read(mod, param)
+    value1 = value1 + 3
+    value2 = value2 + 3
+    value3 = value3 + 3
+
+    return string_format("%d,%d,%d", value1, value2, value3)
+end
+
+local totalvalue = 0
+function _M.set(mod, st_array, pre_array, cur_array, interval)
+    totalvalue = totalvalue + cur_array[2]
+
+    st_array[1] = cur_array[1] - pre_array[1]
+    st_array[2] = (cur_array[1] - pre_array[1]) * 100.0 / totalvalue
+    st_array[3] = cur_array[3]
+
+    return st_array, pre_array, cur_array
+end
+
+function _M.register()
+    return {
+        opt = "--test",
+        usage = "test information",
+        info = info,
+    }
+end
+
+return _M
diff --git a/luadevel/tsarluadevel b/luadevel/tsarluadevel
new file mode 100755
index 0000000..c6e046a
--- /dev/null
+++ b/luadevel/tsarluadevel
@@ -0,0 +1,42 @@
+#!/bin/sh
+
+# check argc
+usage()
+{
+  echo "Usage:"
+  echo "tsarluadevel modname"
+  exit 0
+}
+install()
+{
+ echo "install:make install"
+ echo "uninstall:make uninstall"
+ echo "test:tsar --list or tsar --lua_$modname --live -i 1"
+}
+if [ $# -ne 1 ]
+then
+ usage
+fi
+
+modname=$1
+install_path='/usr/local/tsar/luadevel'
+
+for file in mod_lua_test.lua mod_lua_test.conf Makefile.test
+do
+ if [ ! -e "$install_path/$file" ] ;then
+  echo "$install_path/$file not exist!"
+  echo "make sure you have run 'make tsarluadevel' when install tsar."
+  exit 1
+ fi
+done
+
+
+# mk new mod_test
+mkdir -p $modname
+sed -e "s/test/lua_$modname/g" < $install_path/mod_lua_test.lua > ./$modname/mod_lua_$modname.lua
+sed -e "s/test/lua_$modname/g" < $install_path/mod_lua_test.conf > ./$modname/mod_lua_$modname.conf
+sed -e "s/test/lua_$modname/g" < $install_path/Makefile.test > ./$modname/Makefile
+if [ $? -eq 0 ]
+then
+ install
+fi
diff --git a/lualib/Makefile b/lualib/Makefile
new file mode 100644
index 0000000..d5a3b29
--- /dev/null
+++ b/lualib/Makefile
@@ -0,0 +1,18 @@
+LUACJSON = lua-cjson-2.1.0
+LUASOCKET = luasocket-2.0.2
+DIRS = $(LUACJSON) $(LUASOCKET)
+
+INCLUDE_DIR ?= $(CURDIR)/../src/obj/include/luajit-2.0
+INSTALL_DIR ?= /usr/local/tsar/lualib
+
+all:
+	for i in $(DIRS); do tar --no-same-owner -zxf $$i.tar.gz; done
+	make -C $(LUACJSON) LUA_INCLUDE_DIR=$(INCLUDE_DIR)
+	make -C $(LUASOCKET) LUAINC=-I$(INCLUDE_DIR)
+
+install:
+	@make -C $(LUACJSON) LUA_CMODULE_DIR=$(INSTALL_DIR) LUA_MODULE_DIR=$(INSTALL_DIR) install
+	@make -C $(LUASOCKET) INSTALL_TOP_SHARE=$(INSTALL_DIR) INSTALL_TOP_LIB=$(INSTALL_DIR) install
+
+clean:
+	for i in $(DIRS); do make -C $$i clean; done
diff --git a/lualib/lua-cjson-2.1.0.tar.gz b/lualib/lua-cjson-2.1.0.tar.gz
new file mode 100644
index 0000000..eca1eb3
Binary files /dev/null and b/lualib/lua-cjson-2.1.0.tar.gz differ
diff --git a/lualib/luasocket-2.0.2.tar.gz b/lualib/luasocket-2.0.2.tar.gz
new file mode 100644
index 0000000..0791145
Binary files /dev/null and b/lualib/luasocket-2.0.2.tar.gz differ
diff --git a/modules/Makefile b/modules/Makefile
index 7ab2e05..d13a515 100644
--- a/modules/Makefile
+++ b/modules/Makefile
@@ -1,16 +1,22 @@
-CFLAGS = -Wall -fPIC --shared -g
+CFLAGS = -MD -Wall -fPIC --shared -g -O2 -Wno-strict-aliasing
 CC = gcc
 INCLUDE_DIR = ../include
-LINK = $(CC) -I$(INCLUDE_DIR) $(CFLAGS)
+LINK = $(CC) -I$(INCLUDE_DIR) -I../src/obj/include $(CFLAGS)
 
+UNAME_S := $(shell uname -s)
+ifeq ($(UNAME_S),Darwin)
+	LINK += -Wl,-undefined -Wl,dynamic_lookup
 
-OBJS =  mod_swap.so mod_partition.so mod_cpu.so mod_mem.so mod_lvs.so mod_haproxy.so \
-	mod_traffic.so mod_squid.so mod_load.so mod_tcp.so mod_udp.so mod_tcpx.so \
-	mod_apache.so mod_pcsw.so mod_io.so mod_nginx.so mod_cgblkio.so \
-	mod_cgcpu.so mod_cgmem.so mod_ncpu.so mod_rndc.so \
-	mod_ts_cache.so mod_ts_client.so mod_ts_err.so mod_ts_os.so mod_ts_storage.so mod_ts_conn.so mod_ts_codes.so\
-	mod_swift.so mod_swift_code.so mod_swift_store.so mod_swift_fwd.so \
-        mod_swift_tcmalloc.so mod_tmd.so mod_percpu.so
+	OBJS = mod_apache.so mod_cpu.so mod_haproxy.so mod_load.so mod_swap.so\
+		   mod_lvs.so mod_mem.so mod_ncpu.so mod_nginx.so \
+		   mod_pcsw.so mod_percpu.so mod_pernic.so \
+		   mod_proc.so mod_squid.so mod_tcp.so mod_tcpx.so mod_traffic.so mod_udp.so
+else
+	OBJS = mod_apache.so mod_cpu.so mod_haproxy.so mod_io.so mod_load.so mod_swap.so \
+		   mod_lvs.so mod_mem.so mod_ncpu.so mod_nginx.so \
+		   mod_partition.so mod_pcsw.so mod_percpu.so mod_pernic.so \
+		   mod_proc.so mod_squid.so mod_tcp.so mod_tcpx.so mod_traffic.so mod_udp.so
+endif
 
 all: $(OBJS)
 
@@ -18,3 +24,7 @@ $(OBJS): %.so: %.c
 	$(LINK) $< -o $@
 clean:
 	rm -f *.so;
+	rm -f *.d;
+	rm -rf *.dSYM;
+
+-include $(OBJS:.so=.d)
diff --git a/modules/mod_apache.c b/modules/mod_apache.c
index 1c6c9b0..e1d27e0 100644
--- a/modules/mod_apache.c
+++ b/modules/mod_apache.c
@@ -7,123 +7,145 @@
 
 char *apache_usage = "    --apache            apache statistics";
 
-struct stats_apache{
-	unsigned long long query;
-	unsigned long long response_time;
-	unsigned long long kBytes_sent;
-	unsigned int busy_proc;        
-	unsigned int idle_proc;
+struct stats_apache {
+    unsigned int        busy_proc;
+    unsigned int        idle_proc;
+    unsigned long long  query;
+    unsigned long long  response_time;
+    unsigned long long  kBytes_sent;
 };
 
 #define STATS_APACHE_SIZE (sizeof(struct stats_apache))
 
 
 struct hostinfo {
-	char *host;
-	int port;
+    char *host;
+    int port;
 };
 
-void init_host_info(struct hostinfo *p)
+void
+init_host_info(struct hostinfo *p)
 {
-	p->host = strdup("127.0.0.1");
-	p->port = 80;
+    p->host = strdup("127.0.0.1");
+    p->port = 80;
 }
 
-void read_apache_stats(struct module *mod)
+void
+read_apache_stats(struct module *mod)
 {
-	int fd, n, m, sockfd, send, pos;
-	char buf[LEN_4096] = {0}, request[LEN_4096], line[LEN_4096],
-	     buff[LEN_4096];
-	memset(buf, 0, LEN_4096);
-	struct sockaddr_in servaddr;
-	FILE *stream = NULL;
-	/* FIX me */
-	char *cmd = "server-status?auto";
-	struct hostinfo hinfo;
-	init_host_info(&hinfo);
-	struct stats_apache st_apache;
-	memset(&st_apache, 0, sizeof(struct stats_apache));
-	if ((fd = open(APACHERT, O_RDONLY , 0644)) < 0 ){
-		return;
-	}
-	if ((n = read(fd, buff, 16)) != 16) {
-		return;
-	}
-	st_apache.query = * (unsigned long long *)buff;
-	st_apache.response_time = * (unsigned long long *)&buff[8];
-	/*fullfil another member int the structure*/
-	sockfd = socket(AF_INET, SOCK_STREAM, 0);
-	bzero(&servaddr, sizeof(servaddr));
-	servaddr.sin_family = AF_INET;
-	servaddr.sin_port = htons(hinfo.port);
-	inet_pton(AF_INET, hinfo.host, &servaddr.sin_addr);
-	sprintf(request, 
-			"GET /%s HTTP/1.0\r\n"
-			"User-Agent: Wget/1.9\r\n"
-			"Host: %s\r\n"
-			"Accept:*/*\r\n"
-			"Connection: Close\r\n\r\n",
-			cmd, hinfo.host);
-
-	if ((m = connect(sockfd, (struct sockaddr *) &servaddr,
-					sizeof(servaddr))) == -1 ) {
-		goto writebuf;
-	}
-
-	if ((send = write(sockfd, request, strlen(request))) == -1) {
-		goto writebuf;
-	}
-	stream = fdopen(sockfd, "r");
-	while(fgets(line, LEN_4096, stream) != NULL) {
-		if(!strncmp(line, "Total kBytes:", 13)) {
-			sscanf(line + 14, "%llu", &st_apache.kBytes_sent);
-		} else if (!strncmp(line, "BusyWorkers:", 12)) {
-			sscanf(line + 13, "%d", &st_apache.busy_proc);
-		} else if (!strncmp(line, "IdleWorkers:", 12)) {
-			sscanf(line + 13, "%d", &st_apache.idle_proc);
-		}
-		else
-			;
-		memset(line, 0, LEN_4096);
-	}
+    int fd, n, m, sockfd, send, pos;
+    char buf[LEN_4096] = {0}, request[LEN_4096], line[LEN_4096],
+         buff[LEN_4096];
+    memset(buf, 0, LEN_4096);
+    struct sockaddr_in servaddr;
+    FILE *stream = NULL;
+    /* FIX me */
+    char *cmd = "server-status?auto";
+    struct stats_apache st_apache;
+    memset(&st_apache, 0, sizeof(struct stats_apache));
+    struct hostinfo hinfo;
+    memset(&hinfo, 0, sizeof(struct hostinfo));
+
+    if ((fd = open(APACHERT, O_RDONLY , 0644)) < 0 ){
+        return;
+    }
+    sockfd = socket(AF_INET, SOCK_STREAM, 0);
+    if (sockfd < 0) {
+        goto last;
+    }
+    if ((n = read(fd, buff, 16)) != 16) {
+        goto last;
+    }
+    st_apache.query = * (unsigned long long *)buff;
+    st_apache.response_time = * (unsigned long long *)&buff[8];
+    /*fullfil another member int the structure*/
+    init_host_info(&hinfo);
+    bzero(&servaddr, sizeof(servaddr));
+    servaddr.sin_family = AF_INET;
+    servaddr.sin_port = htons(hinfo.port);
+    inet_pton(AF_INET, hinfo.host, &servaddr.sin_addr);
+    sprintf(request,
+            "GET /%s HTTP/1.0\r\n"
+            "User-Agent: Wget/1.9\r\n"
+            "Host: %s\r\n"
+            "Accept:*/*\r\n"
+            "Connection: Close\r\n\r\n",
+            cmd, hinfo.host);
+
+    if ((m = connect(sockfd, (struct sockaddr *) &servaddr,
+                    sizeof(servaddr))) == -1 ) {
+        goto writebuf;
+    }
+
+    if ((send = write(sockfd, request, strlen(request))) == -1) {
+        goto writebuf;
+    }
+    stream = fdopen(sockfd, "r");
+    if (!stream) {
+        goto last;
+    }
+    while(fgets(line, LEN_4096, stream) != NULL) {
+        if(!strncmp(line, "Total kBytes:", 13)) {
+            sscanf(line + 14, "%llu", &st_apache.kBytes_sent);
+
+        } else if (!strncmp(line, "BusyWorkers:", 12)) {
+            sscanf(line + 13, "%d", &st_apache.busy_proc);
+
+        } else if (!strncmp(line, "IdleWorkers:", 12)) {
+            sscanf(line + 13, "%d", &st_apache.idle_proc);
+
+        } else {
+            ;
+        }
+        memset(line, 0, LEN_4096);
+    }
 writebuf:
-	pos = sprintf(buf,"%lld,%lld,%lld,%d,%d",
-			st_apache.query,
-			st_apache.response_time / 1000,
-			st_apache.kBytes_sent,
-			st_apache.busy_proc,
-			st_apache.idle_proc);
-	buf[pos] = '\0';
-	if (stream)
-		fclose(stream);
-	close(fd);
-	set_mod_record(mod, buf);
-	free(hinfo.host);
+    pos = sprintf(buf, "%lld,%lld,%lld,%d,%d",
+            st_apache.query,
+            st_apache.response_time / 1000,
+            st_apache.kBytes_sent,
+            st_apache.busy_proc,
+            st_apache.idle_proc);
+    buf[pos] = '\0';
+    if (stream) {
+        if (fclose(stream) < 0) {
+            goto last;
+        }
+    }
+    set_mod_record(mod, buf);
+last:
+    close(fd);
+    if (sockfd) {
+        close(sockfd);
+    }
+    free(hinfo.host);
 }
 
-static void set_apache_record(struct module *mod, double st_array[],
-		U_64 pre_array[], U_64 cur_array[], int inter)
+static void
+set_apache_record(struct module *mod, double st_array[],
+    U_64 pre_array[], U_64 cur_array[], int inter)
 {
-	int i;
-	/* set st record */
-	if(cur_array[0] >= pre_array[0])
-		st_array[0] = (cur_array[0] - pre_array[0]) / (inter * 1.0);
-	if((cur_array[1] >= pre_array[1]) && (cur_array[0] > pre_array[0]))
-		st_array[1] = (cur_array[1] - pre_array[1]) / ((cur_array[0] - pre_array[0]) * 1.0);
-	if(cur_array[2] >= pre_array[2])
-		st_array[2] = (cur_array[2] - pre_array[2]) / (inter * 1.0);
-	for (i = 3; i <= 4; i++) st_array[i] = cur_array[i];
+    int i;
+    /* set st record */
+    if(cur_array[0] >= pre_array[0])
+        st_array[0] = (cur_array[0] - pre_array[0]) / (inter * 1.0);
+    if((cur_array[1] >= pre_array[1]) && (cur_array[0] > pre_array[0]))
+        st_array[1] = (cur_array[1] - pre_array[1]) / ((cur_array[0] - pre_array[0]) * 1.0);
+    if(cur_array[2] >= pre_array[2])
+        st_array[2] = (cur_array[2] - pre_array[2]) / (inter * 1.0);
+    for (i = 3; i <= 4; i++) st_array[i] = cur_array[i];
 }
 
 static struct mod_info apache_info[] = {
-	{"   qps", SUMMARY_BIT,  0,  STATS_SUB_INTER},
-	{"    rt", SUMMARY_BIT,  0,  STATS_SUB_INTER},
-	{"  sent", DETAIL_BIT,  0,  STATS_SUB_INTER},
-	{"  busy", DETAIL_BIT,  0,  STATS_NULL},
-	{"  idle", DETAIL_BIT,  0,  STATS_NULL},
+    {"   qps", SUMMARY_BIT,  0,  STATS_SUB_INTER},
+    {"    rt", SUMMARY_BIT,  0,  STATS_SUB_INTER},
+    {"  sent", DETAIL_BIT,  0,  STATS_SUB_INTER},
+    {"  busy", DETAIL_BIT,  0,  STATS_NULL},
+    {"  idle", DETAIL_BIT,  0,  STATS_NULL},
 };
 
-void mod_register(struct module *mod)
+void
+mod_register(struct module *mod)
 {
-	register_mod_fileds(mod, "--apache", apache_usage, apache_info, 5, read_apache_stats, set_apache_record);
+    register_mod_fields(mod, "--apache", apache_usage, apache_info, 5, read_apache_stats, set_apache_record);
 }
diff --git a/modules/mod_cgblkio.c b/modules/mod_cgblkio.c
deleted file mode 100644
index a36f443..0000000
--- a/modules/mod_cgblkio.c
+++ /dev/null
@@ -1,244 +0,0 @@
-#include <dirent.h>
-#include <assert.h>
-#include "tsar.h"
-
-static char *cgblkio_usage = "    --cgblkio            cgroup blkio statistics";
-
-#define MAX_GROUP 64
-#define MAX_NAME_LENGTH 128
-#define CGBLKIO_PATH "/cgroup/blkio"
-#define SECTOR_SIZE 512
-#define MAX_DISKNAME 32
-
-#define ISDOT(a)        (a[0] == '.' && (!a[1] || (a[1] == '.' && !a[2])))
-
-unsigned int n_group;
-
-struct cgblkio_group_info{
-	char group_name [MAX_NAME_LENGTH];
-	unsigned long long rd_merges;
-	unsigned long long wr_merges;
-	unsigned long long rd_ios;
-	unsigned long long wr_ios;
-	unsigned long long rd_secs;
-	unsigned long long wr_secs;
-	unsigned long long qusize;
-	unsigned long long wait;
-	unsigned long long svctm;
-};
-
-#define CGBLKIO_GROUP_SIZE (sizeof(struct cgblkio_group_info))
-struct cgblkio_group_info blkio_groups[MAX_GROUP];
-
-struct blkio_info{
-	char disk[MAX_DISKNAME];
-	char type[8];
-	unsigned long long num;
-};
-
-static struct mod_info cgblkio_info[] = {
-	{" rrqms", DETAIL_BIT,  0,  STATS_NULL},
-	{" wrqms", DETAIL_BIT,  0,  STATS_NULL},
-	{"    rs", DETAIL_BIT,  0,  STATS_NULL},
-	{"    ws", DETAIL_BIT,  0,  STATS_NULL},
-	{" rsecs", DETAIL_BIT,  0,  STATS_NULL},
-	{" wsecs", DETAIL_BIT,  0,  STATS_NULL},
-	{"rqsize", DETAIL_BIT,  0,  STATS_NULL},
-	{"qusize", DETAIL_BIT,  0,  STATS_NULL},
-	{" await", DETAIL_BIT,  0,  STATS_NULL},
-	{" svctm", DETAIL_BIT,  0,  STATS_NULL},
-	{"  util", DETAIL_BIT,  0,  STATS_NULL},
-};
-
-
-static void set_cgblkio_record(struct module *mod, double st_array[],
-		U_64 pre_array[], U_64 cur_array[], int inter)
-{
-	int i;
-
-	for(i = 0; i < 9; i++){
-		if(cur_array[i] < pre_array[i]){
-			pre_array[i] = cur_array[i];
-		}
-	}
-
-	unsigned long long rd_merges = cur_array[0] - pre_array[0];
-	unsigned long long wr_merges = cur_array[1] - pre_array[1];
-	unsigned long long rd_ios = cur_array[2] - pre_array[2];
-	unsigned long long wr_ios = cur_array[3] - pre_array[3];
-	unsigned long long rd_secs = cur_array[4] - pre_array[4];
-	unsigned long long wr_secs = cur_array[5] - pre_array[5];
-	unsigned long long qusize = cur_array[6] - pre_array[6];
-	unsigned long long svctm = cur_array[8] - pre_array[8];
-	unsigned long long await = cur_array[7] - pre_array[7] + svctm;
-	unsigned long long n_ios = rd_ios + wr_ios;
-	unsigned long long n_kbytes = (rd_secs + wr_secs) / 2;
-
-	st_array[0] = rd_merges / (inter * 1.0);
-	st_array[1] = wr_merges / (inter * 1.0);
-	st_array[2] = rd_ios / (inter * 1.0);
-	st_array[3] = wr_ios / (inter * 1.0);
-	st_array[4] = rd_secs / (inter * 1.0);
-	st_array[5] = wr_secs / (inter * 1.0);
-	st_array[6] = n_ios ? n_kbytes / n_ios : 0.0;
-	st_array[7] = qusize / (inter * 1.0);
-	st_array[8] = n_ios ? await / n_ios : 0.0;
-	st_array[9] = n_ios ? svctm / n_ios : 0.0;
-	st_array[10] = svctm / (inter * 1.0);
-
-	if (st_array[10] > 100.0)
-		st_array[10] = 100.0;
-
-}
-
-void print_cgblkio_stats(struct module *mod)
-{
-	int pos = 0,i = 0;
-	char buf[LEN_4096];
-	//memset(buf, 0, LEN_4096);
-	/*set n group's data to buf*/
-	for(i = 0; i < n_group; i++){
-		pos += snprintf(buf + pos, LEN_4096, "%s=%llu,%llu,%llu,%llu,%llu,%llu,%llu,%llu,%llu",
-				blkio_groups[i].group_name,
-				blkio_groups[i].rd_merges,
-				blkio_groups[i].wr_merges,
-				blkio_groups[i].rd_ios,
-				blkio_groups[i].wr_ios,
-				blkio_groups[i].rd_secs,
-				blkio_groups[i].wr_secs,
-				blkio_groups[i].qusize,
-				blkio_groups[i].wait,
-				blkio_groups[i].svctm);
-		if(pos >= LEN_4096)
-			break;
-		pos += snprintf(buf + pos, LEN_4096, ITEM_SPLIT);
-		if(pos >= LEN_4096)
-			break;
-	}
-	//if(pos){
-	//      buf[pos] = '\0';
-	//}
-	/*notice tsar to store my mult item data*/
-	set_mod_record(mod, buf);
-}
-
-void read_cgblkio_stats(struct module *mod)
-{
-	struct dirent *ent;          /* dirent handle */
-	DIR *dir;
-	char path[128], buffer[128];
-	FILE *iofd;
-	struct blkio_info curr;
-
-	n_group = 0;
-
-	memset(blkio_groups, 0, CGBLKIO_GROUP_SIZE * MAX_GROUP);
-	if ((dir = opendir(CGBLKIO_PATH)) == NULL)
-		return;
-
-	while ((ent = readdir(dir))){
-		if (ent->d_type == DT_DIR && !ISDOT(ent->d_name)) {  //for each group
-			memcpy(&blkio_groups[n_group].group_name, ent->d_name, strlen(ent->d_name)+1);
-
-			snprintf(path, 128, "%s/%s/blkio.io_merged", CGBLKIO_PATH, ent->d_name);
-			if ((iofd = fopen(path, "r")) == NULL) {
-				closedir(dir);
-				return;
-			}
-			while (fgets(buffer, 128, iofd) != NULL) {
-				if (sscanf(buffer, "%s %s %llu", curr.disk, curr.type, &curr.num) == 3) {
-					if (!strncmp(curr.type, "Read", 4))
-						blkio_groups[n_group].rd_merges += curr.num;
-					if (!strncmp(curr.type, "Write", 5))
-						blkio_groups[n_group].wr_merges += curr.num;
-				}
-			}
-			fclose(iofd);
-
-			snprintf(path, 128, "%s/%s/blkio.io_serviced", CGBLKIO_PATH, ent->d_name);
-			if ((iofd = fopen(path, "r")) == NULL) {
-				closedir(dir);
-				return;
-			}
-			while (fgets(buffer, 128, iofd) != NULL) {
-				if (sscanf(buffer, "%s %s %llu", curr.disk, curr.type, &curr.num) == 3) {
-					if (!strncmp(curr.type, "Read", 4))
-						blkio_groups[n_group].rd_ios += curr.num;
-					if (!strncmp(curr.type, "Write", 5))
-						blkio_groups[n_group].wr_ios += curr.num;
-				}
-			}
-			fclose(iofd);
-
-			snprintf(path, 128, "%s/%s/blkio.io_service_bytes", CGBLKIO_PATH, ent->d_name);
-			if ((iofd = fopen(path, "r")) == NULL) {
-				closedir(dir);
-				return;
-			}
-			while (fgets(buffer, 128, iofd) != NULL) {
-				if (sscanf(buffer, "%s %s %llu", curr.disk, curr.type, &curr.num) == 3) {
-					if (!strncmp(curr.type, "Read", 4))
-						blkio_groups[n_group].rd_secs += curr.num / SECTOR_SIZE;
-					if (!strncmp(curr.type, "Write", 5))
-						blkio_groups[n_group].wr_secs += curr.num / SECTOR_SIZE;
-				}
-			}
-			fclose(iofd);
-
-			snprintf(path, 128, "%s/%s/blkio.io_queued", CGBLKIO_PATH, ent->d_name);
-			if ((iofd = fopen(path, "r")) == NULL) {
-				closedir(dir);
-				return;
-			}
-			while (fgets(buffer, 128, iofd) != NULL) {
-				if (sscanf(buffer, "%s %s %llu", curr.disk, curr.type, &curr.num) == 3) {
-					if (!strncmp(curr.type, "Read", 4))
-						blkio_groups[n_group].qusize += curr.num;
-					if (!strncmp(curr.type, "Write", 5))
-						blkio_groups[n_group].qusize += curr.num;
-				}
-			}
-			fclose(iofd);
-
-			snprintf(path, 128, "%s/%s/blkio.io_service_time", CGBLKIO_PATH, ent->d_name);
-			if ((iofd = fopen(path, "r")) == NULL) {
-				closedir(dir);
-				return;
-			}
-			while (fgets(buffer, 128, iofd) != NULL) {
-				if (sscanf(buffer, "%s %s %llu", curr.disk, curr.type, &curr.num) == 3) {
-					if (!strncmp(curr.type, "Read", 4)) 
-						blkio_groups[n_group].svctm += (unsigned long long)(curr.num / 1000000); //in ms
-					if (!strncmp(curr.type, "Write", 5)) 
-						blkio_groups[n_group].svctm += (unsigned long long )(curr.num / 1000000);
-				}
-			}
-			fclose(iofd);
-
-			snprintf(path, 128, "%s/%s/blkio.io_wait_time", CGBLKIO_PATH, ent->d_name);
-			if ((iofd = fopen(path, "r")) == NULL) {
-				closedir(dir);
-				return;
-			}
-			while (fgets(buffer, 128, iofd) != NULL) {
-				if (sscanf(buffer, "%s %s %llu", curr.disk, curr.type, &curr.num) == 3) {
-					if (!strncmp(curr.type, "Read", 4))
-						blkio_groups[n_group].wait += (unsigned long long)(curr.num / 1000000);
-					if (!strncmp(curr.type, "Write", 5))
-						blkio_groups[n_group].wait += (unsigned long long)(curr.num / 1000000);
-				}
-			}
-			fclose(iofd);
-
-			n_group ++;
-		}
-	}
-
-	closedir(dir);
-	print_cgblkio_stats(mod);
-}
-
-void mod_register(struct module *mod)
-{
-	register_mod_fileds(mod, "--cgblkio", cgblkio_usage, cgblkio_info, 11, read_cgblkio_stats, set_cgblkio_record);
-}
diff --git a/modules/mod_cgcpu.c b/modules/mod_cgcpu.c
deleted file mode 100644
index 6dc15d7..0000000
--- a/modules/mod_cgcpu.c
+++ /dev/null
@@ -1,143 +0,0 @@
-#include <dirent.h>
-#include <assert.h>
-#include "tsar.h"
-
-static char *cgcpu_usage = "    --cgcpu            cgroup cpu statistics";
-
-#define MAX_GROUP 64
-#define MAX_TASK 1024
-#define MAX_NAME_LENGTH 128
-#define CGCPU_PATH "/cgroup/cpu"
-
-#define ISDOT(a)        (a[0] == '.' && (!a[1] || (a[1] == '.' && !a[2])))
-
-unsigned int n_group;
-
-struct task_info{
-	int pid;
-}tasks[MAX_TASK];
-
-struct sched_info {
-	char name[512];
-	char none[4];
-	double time;
-};
-
-struct cgcpu_group_info{
-	char group_name [MAX_NAME_LENGTH];
-	double sum_exec_runtime;     /*sum of exec runtime counters*/
-};
-struct cgcpu_group_info cgcpu_groups[MAX_GROUP];
-#define CGCPU_GROUP_SIZE (sizeof(struct cgcpu_group_info))
-
-static struct mod_info cgcpu_info[] = {
-	{"  util", DETAIL_BIT,  0,  STATS_SUB},
-};
-
-
-static void set_cgcpu_record(struct module *mod, double st_array[],
-		U_64 pre_array[], U_64 cur_array[], int inter)
-{
-	int i;
-	for (i = 0; i < mod->n_col; i++) {
-		if (cur_array[i] >= pre_array[i]) {
-			st_array[i] = ( cur_array[i] - pre_array[i] ) / (10000.0 * inter);
-			if (st_array[i] > 100.0)
-				st_array[i] = 100.0;
-		}
-	}
-}
-
-void print_cgcpu_stats(struct module *mod)
-{
-	int pos = 0,i=0;
-	char buf[LEN_1024];
-	//memset(buf, 0, LEN_1024);
-	/*set n group's data to buf*/
-	for(i = 0; i < n_group; i++){
-		pos += snprintf(buf + pos, LEN_1024, "%s=%llu", cgcpu_groups[i].group_name, (
-					unsigned long long int)(cgcpu_groups[i].sum_exec_runtime * 1000)); //ms->us
-		if(pos >= LEN_4096)
-			break;
-		pos += snprintf(buf + pos, LEN_1024, ITEM_SPLIT);
-		if(pos >= LEN_4096)
-			break;
-	}
-	//if(pos){
-	//	buf[pos] = '\0';
-	//}
-	/*notice tsar to store my mult item data*/
-	set_mod_record(mod, buf);
-}
-
-void read_cgcpu_stats(struct module *mod)
-{
-	struct dirent *ent;          /* dirent handle */
-	DIR *dir;
-	char path[128], buffer[128];
-	const char *scan_fmt = NULL;
-	int n_task = 0, i;
-	FILE *taskfd, *schedfd;
-
-	n_group = 0;
-
-	memset(cgcpu_groups, 0, CGCPU_GROUP_SIZE * MAX_GROUP);
-	if ((dir = opendir(CGCPU_PATH)) == NULL)
-		return;
-
-	while ((ent = readdir(dir))) {
-		if (ent->d_type == DT_DIR && !ISDOT(ent->d_name)) {  //for each group
-			n_task = 0;
-			memcpy(&cgcpu_groups[n_group].group_name, ent->d_name, strlen(ent->d_name)+1);
-
-			snprintf(path, 128, "%s/%s/tasks", CGCPU_PATH, ent->d_name);
-			if ((taskfd = fopen(path, "r")) == NULL) {
-				closedir(dir);
-				return;
-			}
-			while (fgets(buffer, sizeof(buffer), taskfd)) {   //for each task
-				struct task_info curr;
-
-				if (sscanf(buffer, "%d", &curr.pid) == 1) {
-					tasks[n_task].pid = curr.pid;
-					n_task ++;
-				}
-			}
-			n_task --;
-			fclose(taskfd);
-
-			assert(n_task + 1 <= MAX_TASK);
-
-			//read sum_exe_time of each task and add up
-			for (i = 0; i <= n_task; i++) {
-				snprintf(path, 128, "/proc/%d/sched", tasks[i].pid);
-				if ((schedfd = fopen(path,"r")) == NULL) {
-					closedir(dir);
-					return;
-				}
-				scan_fmt = "%s %s %lf";
-				while (fgets(buffer, sizeof(buffer), schedfd)) {
-					int items;
-					char *title="se.sum_exec_runtime";
-					struct sched_info cur;
-
-					items = sscanf(buffer, scan_fmt, &cur.name, &cur.none, &cur.time);
-					if (memcmp(cur.name, title, strlen(title)) == 0) {
-						cgcpu_groups[n_group].sum_exec_runtime += cur.time; //add it to group sum
-						break;
-					}
-				}
-				fclose(schedfd);
-			}
-			n_group ++;
-		}
-	}
-
-	closedir(dir);
-	print_cgcpu_stats(mod);
-}
-
-void mod_register(struct module *mod)
-{
-	register_mod_fileds(mod, "--cgcpu", cgcpu_usage, cgcpu_info, 1, read_cgcpu_stats, set_cgcpu_record);
-}
diff --git a/modules/mod_cgmem.c b/modules/mod_cgmem.c
deleted file mode 100644
index 76ec95c..0000000
--- a/modules/mod_cgmem.c
+++ /dev/null
@@ -1,136 +0,0 @@
-#include <dirent.h>
-#include <assert.h>
-#include "tsar.h"
-
-static char *cgmem_usage = "    --cgmem            cgroup memory statistics";
-
-#define MAX_GROUP 64
-#define MAX_NAME_LENGTH 128
-#define CGMEM_PATH "/cgroup/memory"
-#define CGMEM_UNIT ( 1024 )  //in KB
-
-#define ISDOT(a)        (a[0] == '.' && (!a[1] || (a[1] == '.' && !a[2])))
-
-unsigned int n_group;
-
-struct cgmem_group_info{
-	char group_name [MAX_NAME_LENGTH];
-	unsigned long cache;
-	unsigned long rss;
-	unsigned long swap;
-	unsigned long inanon;
-	unsigned long acanon;
-	unsigned long infile;
-	unsigned long acfile;
-};
-struct cgmem_group_info cgmem_groups[MAX_GROUP];
-#define CGMEM_GROUP_SIZE (sizeof(struct cgmem_group_info))
-
-static struct mod_info cgmem_info[] = {
-	{"   mem", DETAIL_BIT,  0,  STATS_NULL},
-	{"  swap", DETAIL_BIT,  0,  STATS_NULL},
-	{"inanon", DETAIL_BIT,  0,  STATS_NULL},
-	{"acanon", DETAIL_BIT,  0,  STATS_NULL},
-	{"infile", DETAIL_BIT,  0,  STATS_NULL},
-	{"acfile", DETAIL_BIT,  0,  STATS_NULL},
-};
-
-
-static void set_cgmem_record(struct module *mod, double st_array[],
-		U_64 pre_array[], U_64 cur_array[], int inter)
-{
-	int i;
-	for (i = 0; i < mod->n_col; i++) {
-		st_array[i] = cur_array[i] / CGMEM_UNIT;
-	}
-}
-
-void print_cgmem_stats(struct module *mod)
-{
-	int pos = 0,i = 0;
-	char buf[LEN_4096];
-	//memset(buf, 0, LEN_4096);
-
-	/*set n group's data to buf*/
-	for(i = 0; i < n_group; i++){
-		pos += snprintf(buf + pos, LEN_4096, "%s=%lu,%lu,%lu,%lu,%lu,%lu",
-				cgmem_groups[i].group_name,
-				cgmem_groups[i].cache + cgmem_groups[i].rss,
-				cgmem_groups[i].swap,
-				cgmem_groups[i].inanon,
-				cgmem_groups[i].acanon,
-				cgmem_groups[i].infile,
-				cgmem_groups[i].acfile);
-		if(pos >= LEN_4096)
-			break;
-		pos += snprintf(buf + pos, LEN_4096, ITEM_SPLIT);
-		if(pos >= LEN_4096)
-			break;
-	}
-	//if(pos){
-	//      buf[pos] = '\0';
-	//}
-	/*notice tsar to store my mult item data*/
-	set_mod_record(mod, buf);
-}
-
-void read_cgmem_stats(struct module *mod)
-{
-	struct dirent *ent;          /* dirent handle */
-	DIR *dir;
-	char path[128];
-	char line[LEN_128];
-	FILE *memfd;
-
-	n_group = 0;
-
-	memset(cgmem_groups, 0, CGMEM_GROUP_SIZE * MAX_GROUP);
-	if ((dir = opendir(CGMEM_PATH)) == NULL)
-		return;
-
-	while ((ent = readdir(dir))){
-		if (ent->d_type == DT_DIR && !ISDOT(ent->d_name)) {  //for each group
-			memcpy(&cgmem_groups[n_group].group_name, ent->d_name, strlen(ent->d_name)+1);
-			snprintf(path, 128, "%s/%s/memory.stat", CGMEM_PATH, ent->d_name);
-			if ((memfd = fopen(path, "r")) == NULL) {
-				closedir(dir);
-				return;
-			}
-
-			while (fgets(line, 128, memfd) != NULL) {
-				if (!strncmp(line, "cache", 5)) {
-					sscanf(line + 5, "%lu", &cgmem_groups[n_group].cache);
-				}
-				else if (!strncmp(line, "rss", 3)) {
-					sscanf(line + 3, "%lu", &cgmem_groups[n_group].rss);
-				}
-				else if (!strncmp(line, "swap", 4)) {
-					sscanf(line + 4, "%lu", &cgmem_groups[n_group].swap);
-				}
-				else if (!strncmp(line, "inactive_anon", 13)) {
-					sscanf(line + 13, "%lu", &cgmem_groups[n_group].inanon);
-				}
-				else if (!strncmp(line, "active_anon", 11)) {
-					sscanf(line + 11, "%lu", &cgmem_groups[n_group].acanon);
-				}
-				else if (!strncmp(line, "inactive_file", 13)) {
-					sscanf(line + 13, "%lu", &cgmem_groups[n_group].infile);
-				}
-				else if (!strncmp(line, "active_file", 11)) {
-					sscanf(line + 11, "%lu", &cgmem_groups[n_group].acfile);
-				}
-			}
-
-			fclose(memfd);
-			n_group ++;
-		}
-	}
-
-	closedir(dir);
-	print_cgmem_stats(mod);
-}
-
-void mod_register(struct module *mod)
-{
-	register_mod_fileds(mod, "--cgmem", cgmem_usage, cgmem_info, 6, read_cgmem_stats, set_cgmem_record);
-}
diff --git a/modules/mod_cpu.c b/modules/mod_cpu.c
index ca4ccc7..01e463c 100644
--- a/modules/mod_cpu.c
+++ b/modules/mod_cpu.c
@@ -4,120 +4,164 @@
  * Structure for CPU infomation.
  */
 struct stats_cpu {
-	unsigned long long cpu_user;
-	unsigned long long cpu_nice;
-	unsigned long long cpu_sys;
-	unsigned long long cpu_idle;
-	unsigned long long cpu_iowait;
-	unsigned long long cpu_steal;
-	unsigned long long cpu_hardirq;
-	unsigned long long cpu_softirq;
-	unsigned long long cpu_guest;
+    unsigned long long cpu_user;
+    unsigned long long cpu_nice;
+    unsigned long long cpu_sys;
+    unsigned long long cpu_idle;
+    unsigned long long cpu_iowait;
+    unsigned long long cpu_steal;
+    unsigned long long cpu_hardirq;
+    unsigned long long cpu_softirq;
+    unsigned long long cpu_guest;
+    unsigned long long cpu_number;
 };
 
 #define STATS_CPU_SIZE (sizeof(struct stats_cpu))
 
 static char *cpu_usage = "    --cpu               CPU share (user, system, interrupt, nice, & idle)";
+static int   cpu_quota = 1;
 
 
-static void read_cpu_stats(struct module *mod)
+static void
+read_cpu_stats(struct module *mod)
 {
-	FILE *fp;
-	char line[LEN_4096];
-	char buf[LEN_4096];
-	memset(buf, 0, LEN_4096);
-	struct stats_cpu st_cpu;
-	memset(&st_cpu, 0, sizeof(struct stats_cpu));
-	//unsigned long long cpu_util;
-	if ((fp = fopen(STAT, "r")) == NULL) {
-		return;
-	}
-	while (fgets(line, LEN_4096, fp) != NULL) {
-		if (!strncmp(line, "cpu ", 4)) {
-			/*
-			 * Read the number of jiffies spent in the different modes
-			 * (user, nice, etc.) among all proc. CPU usage is not reduced
-			 * to one processor to avoid rounding problems.
-			 */
-			sscanf(line+5, "%llu %llu %llu %llu %llu %llu %llu %llu %llu",
-					&st_cpu.cpu_user,
-					&st_cpu.cpu_nice,
-					&st_cpu.cpu_sys,
-					&st_cpu.cpu_idle,
-					&st_cpu.cpu_iowait,
-					&st_cpu.cpu_hardirq,
-					&st_cpu.cpu_softirq,
-					&st_cpu.cpu_steal,
-					&st_cpu.cpu_guest);
-		}
-	}
-	/* cpu_util =  */
-	/*      st_cpu.cpu_user + st_cpu.cpu_sys + */
-	/*      st_cpu.cpu_hardirq + st_cpu.cpu_softirq; */
-
-	int pos = sprintf(buf, "%llu,%llu,%llu,%llu,%llu,%llu,%llu,%llu,%llu",
-			/* the store order is not same as read procedure */
-			st_cpu.cpu_user,
-			st_cpu.cpu_sys,
-			st_cpu.cpu_iowait,
-			st_cpu.cpu_hardirq,
-			st_cpu.cpu_softirq,
-			st_cpu.cpu_idle,
-			st_cpu.cpu_nice,
-			st_cpu.cpu_steal,
-			st_cpu.cpu_guest);
-
-	buf[pos] = '\0';
-	set_mod_record(mod, buf);
-	fclose(fp);
-	return;
+    FILE   *fp, *ncpufp;
+    char   *max_cpu;
+    char    line[LEN_4096];
+    char    buf[LEN_4096];
+    struct  stats_cpu st_cpu;
+
+    memset(buf, 0, LEN_4096);
+    memset(&st_cpu, 0, sizeof(struct stats_cpu));
+    //get cpu number for cpushare
+    max_cpu = getenv("SIGMA_MAX_CPU_QUOTA");
+    cpu_quota = max_cpu ? atoi(max_cpu) / 100 : 1;
+    //unsigned long long cpu_util;
+    if ((fp = fopen(STAT, "r")) == NULL) {
+        return;
+    }
+    while (fgets(line, LEN_4096, fp) != NULL) {
+        if (!strncmp(line, "cpu ", 4)) {
+            /*
+             * Read the number of jiffies spent in the different modes
+             * (user, nice, etc.) among all proc. CPU usage is not reduced
+             * to one processor to avoid rounding problems.
+             */
+            sscanf(line + 5, "%llu %llu %llu %llu %llu %llu %llu %llu %llu",
+                    &st_cpu.cpu_user,
+                    &st_cpu.cpu_nice,
+                    &st_cpu.cpu_sys,
+                    &st_cpu.cpu_idle,
+                    &st_cpu.cpu_iowait,
+                    &st_cpu.cpu_hardirq,
+                    &st_cpu.cpu_softirq,
+                    &st_cpu.cpu_steal,
+                    &st_cpu.cpu_guest);
+        }
+    }
+
+    /* get cpu number */
+    if ((ncpufp = fopen("/proc/cpuinfo", "r")) == NULL) {
+        fclose(fp);
+        return;
+    }
+    while (fgets(line, LEN_4096, ncpufp)) {
+        if (!strncmp(line, "processor\t:", 11))
+            st_cpu.cpu_number++;
+    }
+    fclose(ncpufp);
+
+    /* cpu_util =  */
+    /*      st_cpu.cpu_user + st_cpu.cpu_sys + */
+    /*      st_cpu.cpu_hardirq + st_cpu.cpu_softirq; */
+
+    sprintf(buf, "%llu,%llu,%llu,%llu,%llu,%llu,%llu,%llu,%llu,%llu",
+            /* the store order is not same as read procedure */
+            st_cpu.cpu_user,
+            st_cpu.cpu_sys,
+            st_cpu.cpu_iowait,
+            st_cpu.cpu_hardirq,
+            st_cpu.cpu_softirq,
+            st_cpu.cpu_idle,
+            st_cpu.cpu_nice,
+            st_cpu.cpu_steal,
+            st_cpu.cpu_guest,
+            st_cpu.cpu_number);
+
+    set_mod_record(mod, buf);
+    if (fclose(fp) < 0) {
+        return;
+    }
 }
 
-static void set_cpu_record(struct module *mod, double st_array[],
-		U_64 pre_array[], U_64 cur_array[], int inter)
+static void
+set_cpu_record(struct module *mod, double st_array[],
+    U_64 pre_array[], U_64 cur_array[], int inter)
 {
-	U_64 pre_total, cur_total;
-	int i,j;
-	pre_total = cur_total = 0;
-
-	for (i = 0; i < mod->n_col; i++) {
-		if(cur_array[i] < pre_array[i]){
-			for(j = 0; j < 9; j++)
-				st_array[j] = -1;
-			return;
-		}
-		pre_total += pre_array[i];
-		cur_total += cur_array[i];
-	}
-
-	/* no tick changes, or tick overflows */
-	if (cur_total <= pre_total)
-		return;
-	/* set st record */
-	for (i = 0; i < 9; i++) {
-		/* st_array[5] is util, calculate it late */
-		if((i != 5) && (cur_array[i] >= pre_array[i]))
-			st_array[i] = (cur_array[i] - pre_array[i]) * 100.0 / (cur_total - pre_total);
-	}
-
-	/* util = user + sys + hirq + sirq + nice */
-	st_array[5] = st_array[0] + st_array[1] + st_array[3] + st_array[4] + st_array[6];
-}
+    int    i, j;
+    char  *max_cpu;
+    U_64   pre_total, cur_total;
+
+    //get cpu number for cpushare
+    max_cpu = getenv("SIGMA_MAX_CPU_QUOTA");
+    cpu_quota = max_cpu ? atoi(max_cpu) / 100 : 1;
 
+    pre_total = cur_total = 0;
+
+    for (i = 0; i < 9; i++) {
+        if(cur_array[i] < pre_array[i]){
+            for(j = 0; j < 9; j++)
+                st_array[j] = -1;
+            return;
+        }
+        pre_total += pre_array[i];
+        cur_total += cur_array[i];
+    }
+
+    /* no tick changes, or tick overflows */
+    if (cur_total <= pre_total) {
+        for(j = 0; j < 9; j++)
+            st_array[j] = -1;
+        return;
+    }
+
+    /* set st record */
+    for (i = 0; i < 9; i++) {
+        /* st_array[5] is util, calculate it late */
+        if((i != 5) && (cur_array[i] >= pre_array[i]))
+            st_array[i] = (cur_array[i] - pre_array[i]) * 100.0 / (cur_total - pre_total);
+    }
+
+    /* util = 100 - idle - iowait - steal */
+    if (cur_array[5] >= pre_array[5]) {
+        st_array[5] = 100.0 - (cur_array[5] - pre_array[5]) * 100.0 / (cur_total - pre_total) - st_array[2] - st_array[7];
+    }
+    if (cpu_quota > 1) {
+        for (i = 0; i < 9; i++) {
+            st_array[i] = st_array[i] * cur_array[9] / cpu_quota;
+        }
+    }
+
+    st_array[9] = cur_array[9];
+    /* util = user + sys + hirq + sirq + nice */
+    //st_array[5] = st_array[0] + st_array[1] + st_array[3] + st_array[4] + st_array[6];
+}
 
 static struct mod_info cpu_info[] = {
-	{"  user", DETAIL_BIT,  0,  STATS_NULL},
-	{"   sys", DETAIL_BIT,  0,  STATS_NULL},
-	{"  wait", DETAIL_BIT,  0,  STATS_NULL},
-	{"  hirq", DETAIL_BIT,  0,  STATS_NULL},
-	{"  sirq", DETAIL_BIT,  0,  STATS_NULL},
-	{"  util", SUMMARY_BIT,  0,  STATS_NULL},
-	{"  nice", HIDE_BIT,  0,  STATS_NULL},
-	{" steal", HIDE_BIT,  0,  STATS_NULL},
-	{" guest", HIDE_BIT,  0,  STATS_NULL},
+    {"  user", DETAIL_BIT,  0,  STATS_NULL},
+    {"   sys", DETAIL_BIT,  0,  STATS_NULL},
+    {"  wait", DETAIL_BIT,  0,  STATS_NULL},
+    {"  hirq", DETAIL_BIT,  0,  STATS_NULL},
+    {"  sirq", DETAIL_BIT,  0,  STATS_NULL},
+    {"  util", SUMMARY_BIT,  0,  STATS_NULL},
+    {"  nice", HIDE_BIT,  0,  STATS_NULL},
+    {" steal", HIDE_BIT,  0,  STATS_NULL},
+    {" guest", HIDE_BIT,  0,  STATS_NULL},
+    {"  ncpu", HIDE_BIT,  0,  STATS_NULL},
 };
 
-void mod_register(struct module *mod)
+void
+mod_register(struct module *mod)
 {
-	register_mod_fileds(mod, "--cpu", cpu_usage, cpu_info, 9, read_cpu_stats, set_cpu_record);
+    register_mod_fields(mod, "--cpu", cpu_usage, cpu_info, 10, read_cpu_stats, set_cpu_record);
 }
diff --git a/modules/mod_haproxy.c b/modules/mod_haproxy.c
index 00b0f5f..6f8d055 100644
--- a/modules/mod_haproxy.c
+++ b/modules/mod_haproxy.c
@@ -7,8 +7,7 @@
 
 #define SOCK_PATH "/var/run/haproxy.stat"
 #define HAPROXY "/var/run/haproxy.pid"
-#define HAPROXY_STORE_FMT(d)			\
-	"%ld"d"%ld"d"%ld"d"%ld"d"%ld"d"%ld"
+#define HAPROXY_STORE_FMT(d)            "%ld"d"%ld"d"%ld"d"%ld"d"%ld"d"%ld"
 #define server_port 80
 #define server_address "127.0.0.1"
 #define URL "http://img01.taobaocdn.com/health.gif"
@@ -25,29 +24,28 @@ int np_net_connect(const char *address, int port, int *sd, char* proto);
 int get_http_status();
 int StrToInt(const char* str);
 int get_haproxy_detail();
-int sd; 
+int sd;
 int was_refused = 0;
 int econn_refuse_state = 2;
 int address_family = AF_INET;
 char buffer[MAX_INPUT_BUFFER];
 
-struct stats_haproxy{
-	unsigned long stat;
-	unsigned long uptime;
-	unsigned long conns;
-	unsigned long qps;
-	unsigned long hit;
-	unsigned long rt;
+struct stats_haproxy {
+    unsigned long stat;
+    unsigned long uptime;
+    unsigned long conns;
+    unsigned long qps;
+    unsigned long hit;
+    unsigned long rt;
 };
-//#define STATS_HAPROXY_SIZE       (sizeof(struct stats_haproxy))
 
 static struct mod_info info[] = {
-	{"  stat", SUMMARY_BIT, MERGE_NULL,  STATS_NULL},
-	{"uptime", SUMMARY_BIT, MERGE_NULL,  STATS_NULL},
-	{" conns", DETAIL_BIT, MERGE_NULL,  STATS_NULL},
-	{"   qps", SUMMARY_BIT, MERGE_NULL,  STATS_NULL},
-	{"   hit", SUMMARY_BIT,  MERGE_NULL,  STATS_NULL},
-	{"    rt", DETAIL_BIT,  MERGE_NULL,  STATS_NULL},
+    {"  stat", SUMMARY_BIT, MERGE_NULL,  STATS_NULL},
+    {"uptime", SUMMARY_BIT, MERGE_NULL,  STATS_NULL},
+    {" conns", DETAIL_BIT, MERGE_NULL,  STATS_NULL},
+    {"   qps", SUMMARY_BIT, MERGE_NULL,  STATS_NULL},
+    {"   hit", SUMMARY_BIT,  MERGE_NULL,  STATS_NULL},
+    {"    rt", DETAIL_BIT,  MERGE_NULL,  STATS_NULL},
 };
 
 static char *haproxy_usage = "    --haproxy           haproxy usage";
@@ -58,331 +56,360 @@ struct stats_haproxy st_haproxy;
  * Read swapping statistics from haproxy.stat & 80 port
  *******************************************************
  */
-static void read_haproxy(struct module *mod)
+static void
+read_haproxy(struct module *mod)
 {
-	int i,pos=0;
-	char buf[512];
-
-	memset(&st_haproxy, 0, sizeof(struct stats_haproxy));
-	for (i = 0;i < RETRY;i++)
-		if(get_http_status() == 0 && access(HAPROXY,0) == 0){
-			st_haproxy.stat = 1;
-			break;
-		}
-	if(st_haproxy.stat == 1 && get_haproxy_detail() == 0)
-	{
-		if(DEBUG)
-			printf("get right.\n");
-	}else
-	{
-		if(DEBUG)
-			printf("get wrong.\n");
-	}
-	if(st_haproxy.stat == 1){
-		pos = sprintf(buf, HAPROXY_STORE_FMT(DATA_SPLIT), st_haproxy.stat, st_haproxy.uptime, st_haproxy.conns, st_haproxy.qps, st_haproxy.hit, st_haproxy.rt);
-	}
-	buf[pos] = '\0';
-	set_mod_record(mod, buf);
-	return;
+    int i, pos=0;
+    char buf[512];
+
+    memset(&st_haproxy, 0, sizeof(struct stats_haproxy));
+    for (i = 0;i < RETRY;i++) {
+        if (get_http_status() == 0 && access(HAPROXY, 0) == 0) {
+            st_haproxy.stat = 1;
+            break;
+        }
+    }
+    if (st_haproxy.stat == 1 && get_haproxy_detail() == 0) {
+        if (DEBUG) {
+            printf("get right.\n");
+        }
+
+    } else {
+        if (DEBUG) {
+            printf("get wrong.\n");
+        }
+    }
+    if (st_haproxy.stat == 1) {
+        pos = sprintf(buf, HAPROXY_STORE_FMT(DATA_SPLIT), st_haproxy.stat, st_haproxy.uptime,
+                      st_haproxy.conns, st_haproxy.qps, st_haproxy.hit, st_haproxy.rt);
+    }
+    buf[pos] = '\0';
+    set_mod_record(mod, buf);
+    return;
 }
 
 
-static void set_haproxy_record(struct module *mod, double st_array[],
-		U_64 pre_array[], U_64 cur_array[], int inter)
+static void
+set_haproxy_record(struct module *mod, double st_array[],
+    U_64 pre_array[], U_64 cur_array[], int inter)
 {
-	int i;
-	for (i = 0; i <3; i++) st_array[i] = cur_array[i];
-	if (cur_array[3] > pre_array[3])
-		st_array[3] = (cur_array[3] - pre_array[3]) / inter;
-	else
-		st_array[3] = 0;
-	st_array[4] = cur_array[4] / 10.0;
-	st_array[5] = cur_array[5] / 100.0;
+    int i;
+    for (i = 0; i <3; i++) {
+        st_array[i] = cur_array[i];
+    }
+    if (cur_array[3] > pre_array[3]) {
+        st_array[3] = (cur_array[3] - pre_array[3]) / inter;
+    } else {
+        st_array[3] = 0;
+    }
+    st_array[4] = cur_array[4] / 10.0;
+    st_array[5] = cur_array[5] / 100.0;
 }
 
 
-void mod_register(struct module *mod)
+void
+mod_register(struct module *mod)
 {
-	register_mod_fileds(mod, "--haproxy", haproxy_usage, info, sizeof(info)/sizeof(struct mod_info), read_haproxy, set_haproxy_record);
+    register_mod_fields(mod, "--haproxy", haproxy_usage, info, sizeof(info) / sizeof(struct mod_info), read_haproxy, set_haproxy_record);
 }
 
 
 /* Returns 1 if we're done processing the document body; 0 to keep going */
-	static int
+static int
 document_headers_done (char *full_page)
 {
-	const char *body;
+    const char *body;
 
-	for (body = full_page; *body; body++) {
-		if (!strncmp (body, "\n\n", 2) || !strncmp (body, "\n\r\n", 3))
-			break;
-	}
+    for (body = full_page; *body; body++) {
+        if (!strncmp (body, "\n\n", 2) || !strncmp (body, "\n\r\n", 3))
+            break;
+    }
 
-	if (!*body)
-		return 0;  /* haven't read end of headers yet */
+    if (!*body)
+        return 0;  /* haven't read end of headers yet */
 
-	full_page[body - full_page] = 0;
-	return 1;
+    full_page[body - full_page] = 0;
+    return 1;
 }
 
-	int get_http_status(){
-		if(my_tcp_connect (server_address, server_port, &sd) == 0)
-		{
-			close(sd);
-			if(DEBUG)
-				printf("connect host %s at %d\n",server_address,server_port);
-			return 0;
-		}else
-		{
-			close(sd);
-			return -1;
-			if(DEBUG)
-				printf("cat't connect host %s at %d\n",server_address,server_port);
-		}
-		char *buf;
-		char *full_page;
-		char *page;
-		char *status_line;
-		char *status_code;
-		int http_status;
-		int i = 0;
-		size_t pagesize = 0;
-
-		asprintf (&buf, "GET %s HTTP/1.0\r\nUser-Agent: check_http\r\n", URL);
-		/* tell HTTP/1.1 servers not to keep the connection alive */
-		asprintf (&buf, "%sConnection: close\r\n", buf);
-		if (server_address)
-		{
-			asprintf (&buf, "%sHost: %s:%d\r\n", buf, server_address, server_port);
-		}
-		asprintf (&buf, "%s%s", buf, CRLF);
-		if(DEBUG){
-			printf ("send %s\n", buf);
-		}
-		my_send (buf, strlen (buf));
-		full_page = strdup("");
-		while ((i = my_recv (buffer, MAX_INPUT_BUFFER-1)) > 0) {
-			buffer[i] = '\0';
-			asprintf (&full_page, "%s%s", full_page, buffer);
-			pagesize += i;
-			if (document_headers_done (full_page)) {
-				i = 0;
-				break;
-			}
-		}
-		if(DEBUG){
-			printf("%s\n",full_page);
-		}
-		//error
-		if (i < 0 && errno != ECONNRESET) {
-			printf("HTTP CRITICAL - Error on receive\n");
-		}
-		/* return a CRITICAL status if we couldn't read any data */
-		if (pagesize == (size_t) 0){
-			printf("HTTP CRITICAL - No data received from host\n");
-		}
-		/* close the connect */
-		if(sd) close(sd);
-
-
-		/* find status line and null-terminate it */
-		page = full_page;
-		page += (size_t) strspn (page, "\r\n");
-		status_line = page;
-		status_line[strcspn(status_line, "\r\n")] = 0;
-		//strip(status_line);
-		if(DEBUG)
-			printf ("STATUS: %s\n", status_line);
-		status_code = strchr (status_line, ' ') + sizeof (char);
-		http_status = atoi (status_code);
-		return http_status;
-	}
+int
+get_http_status()
+{
+    if (my_tcp_connect (server_address, server_port, &sd) == 0) {
+        close(sd);
+        if (DEBUG) {
+            printf("connect host %s at %d\n", server_address, server_port);
+        }
+        return 0;
+    } else {
+        close(sd);
+        return -1;
+        if (DEBUG) {
+            printf("cat't connect host %s at %d\n", server_address, server_port);
+        }
+    }
+    int     i = 0;
+    int     http_status;
+    char   *buf;
+    char   *full_page;
+    char   *page;
+    char   *status_line;
+    char   *status_code;
+    size_t  pagesize = 0;
+
+    if (asprintf (&buf, "GET %s HTTP/1.0\r\nUser-Agent: check_http\r\n", URL) < 0) {
+        return -1;
+    }
+    /* tell HTTP/1.1 servers not to keep the connection alive */
+    if (asprintf (&buf, "%sConnection: close\r\n", buf) < 0) {
+        return -1;
+    }
+    if (server_address) {
+        if (asprintf (&buf, "%sHost: %s:%d\r\n", buf, server_address, server_port) < 0) {
+            return -1;
+        }
+    }
+    if (asprintf (&buf, "%s%s", buf, CRLF) < 0){
+        return -1;
+    }
+    if (DEBUG) {
+        printf ("send %s\n", buf);
+    }
+    my_send (buf, strlen (buf));
+    full_page = strdup("");
+    while ((i = my_recv (buffer, MAX_INPUT_BUFFER-1)) > 0) {
+        buffer[i] = '\0';
+        if (asprintf (&full_page, "%s%s", full_page, buffer) < 0) {
+            return -1;
+        }
+        pagesize += i;
+        if (document_headers_done (full_page)) {
+            i = 0;
+            break;
+        }
+    }
+    if (DEBUG) {
+        printf("%s\n", full_page);
+    }
+    if (i < 0 && errno != ECONNRESET) {
+        printf("HTTP CRITICAL - Error on receive\n");
+    }
+    /* return a CRITICAL status if we couldn't read any data */
+    if (pagesize == (size_t) 0){
+        printf("HTTP CRITICAL - No data received from host\n");
+    }
+    /* close the connect */
+    if (sd) {
+        close(sd);
+    }
+
+
+    /* find status line and null-terminate it */
+    page = full_page;
+    page += (size_t) strspn (page, "\r\n");
+    status_line = page;
+    status_line[strcspn(status_line, "\r\n")] = 0;
+    if (DEBUG) {
+        printf ("STATUS: %s\n", status_line);
+    }
+    status_code = strchr (status_line, ' ') + sizeof (char);
+    http_status = atoi (status_code);
+    return http_status;
+}
 
 
 /* opens a tcp or udp connection to a remote host or local socket */
-int np_net_connect (const char *host_name, int port, int *sd, char* proto)
+int
+np_net_connect (const char *host_name, int port, int *sd, char* proto)
 {
-	struct sockaddr_in servaddr;
-	struct protoent *ptrp;
-	int result;
-
-	bzero((char *)&servaddr,sizeof(servaddr));
-	servaddr.sin_family=AF_INET;
-	servaddr.sin_port=htons(port);
-	inet_pton(AF_INET, server_address, &servaddr.sin_addr);
-
-	/* map transport protocol name to protocol number */
-	if(((ptrp=getprotobyname(proto)))==NULL){
-		if(DEBUG)
-			printf("Cannot map \"%s\" to protocol number\n",proto);
-		return 3;
-	}
-
-	/* create a socket */
-	*sd=socket(PF_INET,(!strcmp(proto,"udp"))?SOCK_DGRAM:SOCK_STREAM,ptrp->p_proto);
-	if(*sd<0){
-		close(*sd);
-		if(DEBUG)
-			printf("Socket creation failed\n");
-		return 3;
-	}
-	/* open a connection */
-	result=connect(*sd,(struct sockaddr *)&servaddr,sizeof(servaddr));
-	if(result<0){
-		close(*sd);
-		switch(errno){
-			case ECONNREFUSED:
-				if(DEBUG)
-					printf("Connection refused by host\n");
-				break;
-			case ETIMEDOUT:
-				if(DEBUG)
-					printf("Timeout while attempting connection\n");
-				break;
-			case ENETUNREACH:
-				if(DEBUG)
-					printf("Network is unreachable\n");
-				break;
-			default:
-				if(DEBUG)
-					printf("Connection refused or timed out\n");
-		}
-
-		return 2;
-	}
-	return 0;
+    int                 result;
+    struct protoent    *ptrp;
+    struct sockaddr_in  servaddr;
+
+    bzero((char *)&servaddr, sizeof(servaddr));
+    servaddr.sin_family=AF_INET;
+    servaddr.sin_port=htons(port);
+    inet_pton(AF_INET, server_address, &servaddr.sin_addr);
+
+    /* map transport protocol name to protocol number */
+    if (((ptrp = getprotobyname(proto))) == NULL) {
+        if (DEBUG) {
+            printf("Cannot map \"%s\" to protocol number\n", proto);
+        }
+        return 3;
+    }
+
+    /* create a socket */
+    *sd = socket(PF_INET, (!strcmp(proto, "udp"))?SOCK_DGRAM:SOCK_STREAM, ptrp->p_proto);
+    if (*sd < 0) {
+        close(*sd);
+        if (DEBUG) {
+            printf("Socket creation failed\n");
+        }
+        return 3;
+    }
+    /* open a connection */
+    result = connect(*sd, (struct sockaddr *)&servaddr, sizeof(servaddr));
+    if (result < 0) {
+        close(*sd);
+        switch(errno) {
+            case ECONNREFUSED:
+                if (DEBUG) {
+                    printf("Connection refused by host\n");
+                }
+                break;
+            case ETIMEDOUT:
+                if (DEBUG) {
+                    printf("Timeout while attempting connection\n");
+                }
+                break;
+            case ENETUNREACH:
+                if (DEBUG) {
+                    printf("Network is unreachable\n");
+                }
+                break;
+            default:
+                if (DEBUG) {
+                    printf("Connection refused or timed out\n");
+                }
+        }
+
+        return 2;
+    }
+    return 0;
 }
 
-int StrToInt(const char* str){
-	int num = 0;
-	if(str != NULL)
-	{   
-		const char* digit = str;
-		while(*digit != '\0')
-		{   
-			if(*digit >= '0' && *digit <= '9')
-			{   
-				num = num * 10 + (*digit - '0');
-			}else
-			{   
-				num = 0;
-				break;
-			}   
-			digit ++; 
-		}   
-	}   
-	return num;
+int
+StrToInt(const char* str)
+{
+    int num = 0;
+    if (str != NULL) {
+        const char* digit = str;
+        while (*digit != '\0') {
+            if (*digit >= '0' && *digit <= '9') {
+                num = num * 10 + (*digit - '0');
+            } else {
+                num = 0;
+                break;
+            }
+            digit ++;
+        }
+    }
+    return num;
 }
 
-int get_haproxy_detail(void)
+int
+get_haproxy_detail(void)
 {
-	int s, t, len;
-	struct sockaddr_un remote;
-	char str[MAX_SIZE];
-	char show_info[20] = "show info\n";
-	char show_tsar[20] = "show tsar\n";
-	char *p_split;
-	/*result for tsar to show*/
-	if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {
-		close(s);
-		if(DEBUG)
-			perror("socket");
-		return -1;
-	}
-
-	remote.sun_family = AF_UNIX;
-	strcpy(remote.sun_path, SOCK_PATH);
-	len = strlen(remote.sun_path) + sizeof(remote.sun_family);
-	if (connect(s, (struct sockaddr *)&remote, len) == -1) {
-		close(s);
-		if(DEBUG)
-			perror("connect");
-		return -1;
-	}
-	//get info
-	memset(str, '\0', sizeof(str));
-	if (send(s, show_tsar, strlen(show_tsar), 0) == -1) {
-		close(s);
-		if(DEBUG)
-			perror("send");
-		return -1;
-	}
-
-	if ((t=recv(s, str, MAX_SIZE, 0)) > 0) {
-		str[t] = '\0';
-	} else {
-		close(s);
-		if (t < 0 && DEBUG) perror("recv");
-		else if(DEBUG) perror("Server closed connection\n");
-		return -1;
-	}
-	//check if info right
-	if(!strstr(str,"Uptime_sec")){
-		if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {
-			close(s);
-			if(DEBUG)
-				perror("socket");
-			return -1;
-		}
-		//remote.sun_family = AF_UNIX;
-		//strcpy(remote.sun_path, SOCK_PATH);
-		//len = strlen(remote.sun_path) + sizeof(remote.sun_family);
-		if (connect(s, (struct sockaddr *)&remote, len) == -1) {
-			close(s);
-			if(DEBUG)
-				perror("connect");
-			return -1;
-		}
-		//get info
-		memset(str, '\0', sizeof(str));
-		if (send(s, show_info, strlen(show_info), 0) == -1) {
-			close(s);
-			if(DEBUG)
-				perror("send");
-			return -1;
-		}
-
-		if ((t=recv(s, str, MAX_SIZE, 0)) > 0) {
-			str[t] = '\0';
-		} else {
-			close(s);
-			if (t < 0 && DEBUG) perror("recv");
-			else if(DEBUG) perror("Server closed connection\n");
-			return -1;
-		}
-		close(s);
-	}
-	p_split = strtok(str, "\n");
-	while(p_split)
-	{
-		if(strstr(p_split,"total request num:")){
-			sscanf(p_split,"total request num: %ld/", &st_haproxy.qps);
-		}
-		if(strstr(p_split,"total request num/total hit request num/ total conns num:")){
-			sscanf(p_split,"total request num/total hit request num/ total conns num: %ld/", &st_haproxy.qps);
-		}
-		if(strstr(p_split,"mean rt:")){
-			int a ,b;
-			sscanf(p_split,"mean rt: %d.%d (ms)", &a, &b);
-			st_haproxy.rt = a*100+b;
-		}
-		if(strstr(p_split,"req hit ratio:")){
-			int a, b;
-			sscanf(p_split,"req hit ratio: %d.%d ", &a, &b);
-			st_haproxy.hit = a * 1000 + b;
-		}
-		if(strstr(p_split,"Uptime_sec"))
-		{
-			char *p=strstr(p_split," ");
-			st_haproxy.uptime = StrToInt(p+1);
-		}
-		if(strstr(p_split,"CurrConns"))
-		{
-			char *p=strstr(p_split," ");
-			st_haproxy.conns = StrToInt(p+1);
-		}
-		p_split = strtok(NULL, "\n");
-	}
-	close(s);
-	return 0;
+    int                 s, t, len;
+    char                str[MAX_SIZE];
+    char                show_info[20] = "show info\n";
+    char                show_tsar[20] = "show tsar\n";
+    char               *p_split;
+    struct sockaddr_un  remote;
+    /*result for tsar to show*/
+    if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {
+        if (DEBUG) {
+            perror("socket");
+        }
+        return -1;
+    }
+
+    remote.sun_family = AF_UNIX;
+    strcpy(remote.sun_path, SOCK_PATH);
+    len = strlen(remote.sun_path) + sizeof(remote.sun_family);
+    if (connect(s, (struct sockaddr *)&remote, len) == -1) {
+        close(s);
+        if (DEBUG) {
+            perror("connect");
+        }
+        return -1;
+    }
+    memset(str, '\0', sizeof(str));
+    if (send(s, show_tsar, strlen(show_tsar), 0) == -1) {
+        close(s);
+        if (DEBUG) {
+            perror("send");
+        }
+        return -1;
+    }
+
+    t = recv(s, str, MAX_SIZE, 0);
+    close(s);
+	if (t > 0) {
+        str[t] = '\0';
+    } else {
+        if (t < 0 && DEBUG) {
+            perror("recv");
+        } else if (DEBUG) {
+            perror("Server closed connection\n");
+        }
+        return -1;
+    }
+
+    if (!strstr(str, "Uptime_sec")) {
+        if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {
+            if (DEBUG) {
+                perror("socket");
+            }
+            return -1;
+        }
+        if (connect(s, (struct sockaddr *)&remote, len) == -1) {
+            close(s);
+            if (DEBUG) {
+                perror("connect");
+            }
+            return -1;
+        }
+        memset(str, '\0', sizeof(str));
+        if (send(s, show_info, strlen(show_info), 0) == -1) {
+            close(s);
+            if (DEBUG) {
+                perror("send");
+            }
+            return -1;
+        }
+
+        if ((t=recv(s, str, MAX_SIZE, 0)) > 0) {
+            str[t] = '\0';
+        } else {
+            close(s);
+            if (t < 0 && DEBUG) {
+                perror("recv");
+            } else if (DEBUG) {
+                perror("Server closed connection\n");
+            }
+            return -1;
+        }
+        close(s);
+    }
+    p_split = strtok(str, "\n");
+    while (p_split) {
+        if (strstr(p_split, "total request num:")) {
+            sscanf(p_split, "total request num: %ld/", &st_haproxy.qps);
+        }
+        if (strstr(p_split, "total request num/total hit request num/ total conns num:")) {
+            sscanf(p_split, "total request num/total hit request num/ total conns num: %ld/", &st_haproxy.qps);
+        }
+        if (strstr(p_split, "mean rt:")) {
+            int a, b;
+            sscanf(p_split, "mean rt: %d.%d (ms)", &a, &b);
+            st_haproxy.rt = a * 100 + b;
+        }
+        if (strstr(p_split, "req hit ratio:")) {
+            int a, b;
+            sscanf(p_split, "req hit ratio: %d.%d ", &a, &b);
+            st_haproxy.hit = a * 1000 + b;
+        }
+        if (strstr(p_split, "Uptime_sec")) {
+            char *p = strstr(p_split, " ");
+            st_haproxy.uptime = StrToInt(p + 1);
+        }
+        if (strstr(p_split, "CurrConns")) {
+            char *p = strstr(p_split, " ");
+            st_haproxy.conns = StrToInt(p + 1);
+        }
+        p_split = strtok(NULL, "\n");
+    }
+    return 0;
 }
diff --git a/modules/mod_io.c b/modules/mod_io.c
index bd93a2c..1b85b20 100644
--- a/modules/mod_io.c
+++ b/modules/mod_io.c
@@ -14,57 +14,64 @@
 
 char *io_usage = "    --io                Linux I/O performance";
 
-#define MAX_PARTITIONS 16
+#define MAX_PARTITIONS 64
 #define IO_FILE "/proc/diskstats"
 
 struct part_info {
-	unsigned int major;	/* Device major number */
-	unsigned int minor;	/* Device minor number */
-	char name[32];
+    unsigned int major; /* Device major number */
+    unsigned int minor; /* Device minor number */
+    char name[32];
 } partition[MAX_PARTITIONS];
 
-struct blkio_info{
-	unsigned long long rd_ios;	/* Read I/O operations */
-	unsigned long long rd_merges;	/* Reads merged */
-	unsigned long long rd_sectors; /* Sectors read */
-	unsigned long long rd_ticks;	/* Time in queue + service for read */
-	unsigned long long wr_ios;	/* Write I/O operations */
-	unsigned long long wr_merges;	/* Writes merged */
-	unsigned long long wr_sectors; /* Sectors written */
-	unsigned long long wr_ticks;	/* Time in queue + service for write */
-	unsigned long long ticks;	/* Time of requests in queue */
-	unsigned long long aveq;	/* Average queue length */
-}new_blkio[MAX_PARTITIONS];
+struct blkio_info {
+    unsigned long long rd_ios;  /* Read I/O operations */
+    unsigned long long rd_merges;   /* Reads merged */
+    unsigned long long rd_sectors; /* Sectors read */
+    unsigned long long rd_ticks;    /* Time in queue + service for read */
+    unsigned long long wr_ios;  /* Write I/O operations */
+    unsigned long long wr_merges;   /* Writes merged */
+    unsigned long long wr_sectors; /* Sectors written */
+    unsigned long long wr_ticks;    /* Time in queue + service for write */
+    unsigned long long ticks;   /* Time of requests in queue */
+    unsigned long long aveq;    /* Average queue length */
+} new_blkio[MAX_PARTITIONS];
 #define STATS_IO_SIZE       (sizeof(struct blkio_info))
 
-char buffer[256];		/* Temporary buffer for parsing */
+char buffer[256];       /* Temporary buffer for parsing */
 FILE *iofp;                     /* /proc/diskstats*/
 int print_partition = 0;
 int print_device = 1;
 
-unsigned int n_partitions;	/* Number of partitions */
+unsigned int n_partitions = 0;  /* Number of partitions */
+unsigned int max_partitions = MAX_PARTITIONS;  /* Max of partitions */
 
-static struct mod_info io_info[] = { 
-	{" rrqms", DETAIL_BIT,  MERGE_SUM,  STATS_NULL},
-	{" wrqms", DETAIL_BIT,  MERGE_SUM,  STATS_NULL},
-	{"    rs", DETAIL_BIT,  MERGE_SUM,  STATS_NULL},
-	{"    ws", DETAIL_BIT,  MERGE_SUM,  STATS_NULL},
-	{" rsecs", DETAIL_BIT,  MERGE_SUM,  STATS_NULL},
-	{" wsecs", DETAIL_BIT,  MERGE_SUM,  STATS_NULL},
-	{"rqsize", DETAIL_BIT,  MERGE_AVG,  STATS_NULL},
-	{"qusize", DETAIL_BIT,  MERGE_AVG,  STATS_NULL},
-	{" await", DETAIL_BIT,  MERGE_AVG,  STATS_NULL},
-	{" svctm", DETAIL_BIT,  MERGE_AVG,  STATS_NULL},
-	{"  util", SUMMARY_BIT,  MERGE_AVG,  STATS_NULL}
+static struct mod_info io_info[] = {
+    {" rrqms", DETAIL_BIT,  MERGE_SUM,  STATS_NULL},
+    {" wrqms", DETAIL_BIT,  MERGE_SUM,  STATS_NULL},
+    {" %rrqm", DETAIL_BIT,  MERGE_AVG,  STATS_NULL},
+    {" %wrqm", DETAIL_BIT,  MERGE_AVG,  STATS_NULL},
+    {"    rs", DETAIL_BIT,  MERGE_SUM,  STATS_NULL},
+    {"    ws", DETAIL_BIT,  MERGE_SUM,  STATS_NULL},
+    {" rsecs", DETAIL_BIT,  MERGE_SUM,  STATS_NULL},
+    {" wsecs", DETAIL_BIT,  MERGE_SUM,  STATS_NULL},
+    {"rqsize", DETAIL_BIT,  MERGE_AVG,  STATS_NULL},
+    {"rarqsz", DETAIL_BIT,  MERGE_AVG,  STATS_NULL},
+    {"warqsz", DETAIL_BIT,  MERGE_AVG,  STATS_NULL},
+    {"qusize", DETAIL_BIT,  MERGE_AVG,  STATS_NULL},
+    {" await", DETAIL_BIT,  MERGE_AVG,  STATS_NULL},
+    {"rawait", DETAIL_BIT,  MERGE_AVG,  STATS_NULL},
+    {"wawait", DETAIL_BIT,  MERGE_AVG,  STATS_NULL},
+    {" svctm", DETAIL_BIT,  MERGE_AVG,  STATS_NULL},
+    {"  util", SUMMARY_BIT,  MERGE_AVG,  STATS_NULL}
 };
 
 #ifndef IDE_DISK_MAJOR
 #define IDE_DISK_MAJOR(M) ((M) == IDE0_MAJOR || (M) == IDE1_MAJOR || \
-		(M) == IDE2_MAJOR || (M) == IDE3_MAJOR || \
-		(M) == IDE4_MAJOR || (M) == IDE5_MAJOR || \
-		(M) == IDE6_MAJOR || (M) == IDE7_MAJOR || \
-		(M) == IDE8_MAJOR || (M) == IDE9_MAJOR)
-#endif	/* !IDE_DISK_MAJOR */
+        (M) == IDE2_MAJOR || (M) == IDE3_MAJOR || \
+        (M) == IDE4_MAJOR || (M) == IDE5_MAJOR || \
+        (M) == IDE6_MAJOR || (M) == IDE7_MAJOR || \
+        (M) == IDE8_MAJOR || (M) == IDE9_MAJOR)
+#endif  /* !IDE_DISK_MAJOR */
 
 #ifndef SCSI_DISK_MAJOR
 #ifndef SCSI_DISK8_MAJOR
@@ -74,138 +81,148 @@ static struct mod_info io_info[] = {
 #define SCSI_DISK15_MAJOR 135
 #endif
 #define SCSI_DISK_MAJOR(M) ((M) == SCSI_DISK0_MAJOR || \
-		((M) >= SCSI_DISK1_MAJOR && \
-		 (M) <= SCSI_DISK7_MAJOR) || \
-		((M) >= SCSI_DISK8_MAJOR && \
-		 (M) <= SCSI_DISK15_MAJOR))
-#endif	/* !SCSI_DISK_MAJOR */
+        ((M) >= SCSI_DISK1_MAJOR && \
+         (M) <= SCSI_DISK7_MAJOR) || \
+        ((M) >= SCSI_DISK8_MAJOR && \
+         (M) <= SCSI_DISK15_MAJOR))
+#endif  /* !SCSI_DISK_MAJOR */
 
 #ifndef DEVMAP_MAJOR
 #define DEVMAP_MAJOR 253
 #endif
 
 #ifndef COMPAQ_MAJOR
-#define COMPAQ_CISS_MAJOR	104
-#define COMPAQ_CISS_MAJOR7	111
-#define COMPAQ_SMART2_MAJOR	72
-#define COMPAQ_SMART2_MAJOR7	79
+#define COMPAQ_CISS_MAJOR   104
+#define COMPAQ_CISS_MAJOR7  111
+#define COMPAQ_SMART2_MAJOR 72
+#define COMPAQ_SMART2_MAJOR7    79
 #define COMPAQ_MAJOR(M) (((M) >= COMPAQ_CISS_MAJOR && \
-			(M) <= COMPAQ_CISS_MAJOR7) || \
-		((M) >= COMPAQ_SMART2_MAJOR && \
-		 (M) <= COMPAQ_SMART2_MAJOR7))
+            (M) <= COMPAQ_CISS_MAJOR7) || \
+        ((M) >= COMPAQ_SMART2_MAJOR && \
+         (M) <= COMPAQ_SMART2_MAJOR7))
 #endif /* !COMPAQ_MAJOR */
 
-void handle_error(const char *string, int error)
+void
+handle_error(const char *string, int error)
 {
-	if (error) {
-		fputs("iostat: ", stderr);
-		if (errno)
-			perror(string);
-		else
-			fprintf(stderr, "%s\n", string);
-		exit(EXIT_FAILURE);
-	}
+    if (error) {
+        fputs("iostat: ", stderr);
+        if (errno)
+            perror(string);
+        else
+            fprintf(stderr, "%s\n", string);
+        exit(EXIT_FAILURE);
+    }
 }
 
-int printable(unsigned int major, unsigned int minor)
+int
+printable(unsigned int major, unsigned int minor)
 {
-	if (IDE_DISK_MAJOR(major)) {
-		return (!(minor & 0x3F) && print_device)
-			|| ((minor & 0x3F) && print_partition);
-	} else if (SCSI_DISK_MAJOR(major)) {
-		return (!(minor & 0x0F) && print_device)
-			|| ((minor & 0x0F) && print_partition);
-	} else if(COMPAQ_MAJOR(major)){
-		return (!(minor & 0x0F) && print_device)
-			|| ((minor & 0x0F) && print_partition);
-	} else if(DEVMAP_MAJOR == major){
-		return 0;
-	}
-	return 1;	/* if uncertain, print it */
+    if (IDE_DISK_MAJOR(major)) {
+        return (!(minor & 0x3F) && print_device)
+            || ((minor & 0x3F) && print_partition);
+    } else if (SCSI_DISK_MAJOR(major)) {
+        return (!(minor & 0x0F) && print_device)
+            || ((minor & 0x0F) && print_partition);
+    } else if(COMPAQ_MAJOR(major)){
+        return (!(minor & 0x0F) && print_device)
+            || ((minor & 0x0F) && print_partition);
+    }
+    /*
+    } else if(DEVMAP_MAJOR == major){
+        return 0;
+    }
+    */
+    return 1;   /* if uncertain, print it */
 }
 
 /* Get partition names.  Check against match list */
-void initialize()
+void
+initialize()
 {
-	const char *scan_fmt = NULL;
+    const char *scan_fmt = NULL;
 
-	scan_fmt = "%4d %4d %31s %u";
+    scan_fmt = "%4d %4d %31s %u";
 
-	while (fgets(buffer, sizeof(buffer), iofp)) {
-		unsigned int reads = 0;
-		struct part_info curr;
+    while (fgets(buffer, sizeof(buffer), iofp)) {
+        unsigned int reads = 0;
+        struct part_info curr;
 
-		if (sscanf(buffer, scan_fmt, &curr.major, &curr.minor,
-					curr.name, &reads) == 4) {
-			unsigned int p;
+        if (sscanf(buffer, scan_fmt, &curr.major, &curr.minor,
+                    curr.name, &reads) == 4) {
+            unsigned int p;
+            if (n_partitions >= max_partitions) {
+                break;
+            }
 
-			for (p = 0; p < n_partitions
-					&& (partition[p].major != curr.major
-						|| partition[p].minor != curr.minor);
-					p++);
+            for (p = 0; p < n_partitions
+                    && (partition[p].major != curr.major
+                        || partition[p].minor != curr.minor);
+                    p++);
 
-			if (p == n_partitions && p < MAX_PARTITIONS) {
-				if (reads && printable(curr.major,curr.minor)) {
-					partition[p] = curr;
-					n_partitions = p + 1;
-				}
-			}
-		}
-	}
+            if (p == n_partitions && p < MAX_PARTITIONS) {
+                if (reads && printable(curr.major, curr.minor)) {
+                    partition[p] = curr;
+                    n_partitions = p + 1;
+                }
+            }
+        }
+    }
 }
 
-void get_kernel_stats()
+void
+get_kernel_stats()
 {
-	const char *scan_fmt = NULL;
+    const char *scan_fmt = NULL;
 
-	scan_fmt = "%4d %4d %*s %u %u %llu %u %u %u %llu %u %*u %u %u";
+    scan_fmt = "%4d %4d %*s %u %u %llu %u %u %u %llu %u %*u %u %u";
 
-	rewind(iofp);
-	while (fgets(buffer, sizeof(buffer), iofp)) {
-		int items;
-		struct part_info curr;
-		struct blkio_info blkio;
-		memset(&blkio, 0, STATS_IO_SIZE);
-		items = sscanf(buffer, scan_fmt,
-				&curr.major, &curr.minor,
-				&blkio.rd_ios, &blkio.rd_merges,
-				&blkio.rd_sectors, &blkio.rd_ticks, 
-				&blkio.wr_ios, &blkio.wr_merges,
-				&blkio.wr_sectors, &blkio.wr_ticks,
-				&blkio.ticks, &blkio.aveq);
+    rewind(iofp);
+    while (fgets(buffer, sizeof(buffer), iofp)) {
+        int items;
+        struct part_info curr;
+        struct blkio_info blkio;
+        memset(&blkio, 0, STATS_IO_SIZE);
+        items = sscanf(buffer, scan_fmt,
+                &curr.major, &curr.minor,
+                &blkio.rd_ios, &blkio.rd_merges,
+                &blkio.rd_sectors, &blkio.rd_ticks,
+                &blkio.wr_ios, &blkio.wr_merges,
+                &blkio.wr_sectors, &blkio.wr_ticks,
+                &blkio.ticks, &blkio.aveq);
 
-		/*
-		 * Unfortunately, we can report only transfer rates
-		 * for partitions in 2.6 kernels, all other I/O
-		 * statistics are unavailable.
-		 */
-		if (items == 6) {
-			blkio.rd_sectors = blkio.rd_merges;
-			blkio.wr_sectors = blkio.rd_ticks;
-			blkio.rd_ios = 0;
-			blkio.rd_merges = 0;
-			blkio.rd_ticks = 0;
-			blkio.wr_ios = 0;
-			blkio.wr_merges = 0;
-			blkio.wr_ticks = 0;
-			blkio.ticks = 0;
-			blkio.aveq = 0;
-			items = 12;
-		}
+        /*
+         * Unfortunately, we can report only transfer rates
+         * for partitions in 2.6 kernels, all other I/O
+         * statistics are unavailable.
+         */
+        if (items == 6) {
+            blkio.rd_sectors = blkio.rd_merges;
+            blkio.wr_sectors = blkio.rd_ticks;
+            blkio.rd_ios = 0;
+            blkio.rd_merges = 0;
+            blkio.rd_ticks = 0;
+            blkio.wr_ios = 0;
+            blkio.wr_merges = 0;
+            blkio.wr_ticks = 0;
+            blkio.ticks = 0;
+            blkio.aveq = 0;
+            items = 12;
+        }
 
-		if (items == 12) {
-			unsigned int p;
+        if (items == 12) {
+            unsigned int p;
 
-			/* Locate partition in data table */
-			for (p = 0; p < n_partitions; p++) {
-				if (partition[p].major == curr.major
-						&& partition[p].minor == curr.minor) {
-					new_blkio[p] = blkio;
-					break;
-				}
-			}
-		}
-	}
+            /* Locate partition in data table */
+            for (p = 0; p < n_partitions; p++) {
+                if (partition[p].major == curr.major
+                        && partition[p].minor == curr.minor) {
+                    new_blkio[p] = blkio;
+                    break;
+                }
+            }
+        }
+    }
 }
 
 /*
@@ -223,90 +240,106 @@ void get_kernel_stats()
  *   average disk utilization.
  */
 
-void print_partition_stats(struct module *mod)
+void
+print_partition_stats(struct module *mod)
 {
-	int pos = 0;
-	char buf[LEN_4096];
-	memset(buf, 0, LEN_4096);
-	unsigned int p;
+    int pos = 0;
+    char buf[LEN_1M];
+    memset(buf, 0, LEN_1M);
+    unsigned int p;
 
-	for (p = 0; p < n_partitions; p++) {
-		pos += sprintf(buf + pos, "%s=%llu,%llu,%llu,%llu,%llu,%llu,%llu,%llu,%llu,%llu,%d",
-				partition[p].name,
-				new_blkio[p].rd_ios,
-				new_blkio[p].rd_merges,
-				new_blkio[p].rd_sectors,
-				new_blkio[p].rd_ticks,
-				new_blkio[p].wr_ios,
-				new_blkio[p].wr_merges,
-				new_blkio[p].wr_sectors,
-				new_blkio[p].wr_ticks,
-				new_blkio[p].ticks,
-				new_blkio[p].aveq,
-				pos);
-		pos += sprintf(buf + pos, ITEM_SPLIT);
-	}
-	if(pos) {
-		buf[pos] = '\0';
-		set_mod_record(mod, buf);
-	}   
-	rewind(iofp);
-	if(NULL!=iofp){
-		fclose(iofp);
-		iofp =NULL;
-	}
-	return;
+    for (p = 0; p < n_partitions; p++) {
+        pos += snprintf(buf + pos, LEN_1M - pos, "%s=%llu,%llu,%llu,%llu,%llu,%llu,%llu,%llu,%llu,%llu,%d" ITEM_SPLIT,
+                partition[p].name,
+                new_blkio[p].rd_ios,
+                new_blkio[p].rd_merges,
+                new_blkio[p].rd_sectors,
+                new_blkio[p].rd_ticks,
+                new_blkio[p].wr_ios,
+                new_blkio[p].wr_merges,
+                new_blkio[p].wr_sectors,
+                new_blkio[p].wr_ticks,
+                new_blkio[p].ticks,
+                new_blkio[p].aveq,
+                pos);
+        if (strlen(buf) == LEN_1M - 1) {
+            fclose(iofp);
+            return;
+        }
+    }
+    set_mod_record(mod, buf);
+    rewind(iofp);
+    if (NULL != iofp) {
+        if (fclose(iofp) < 0) {
+            return;
+        }
+        iofp =NULL;
+    }
+    return;
 }
 
-void read_io_stat(struct module *mod)
+void
+read_io_stat(struct module *mod, char *parameter)
 {
-	setlinebuf(stdout);
-	//iofp = (FILE *)malloc(sizeof(FILE));
-	/*open current io statistics file*/
-	iofp = fopen(IO_FILE, "r");
-	handle_error("Can't open /proc/diskstats", !iofp);
-	initialize();
-	get_kernel_stats();
-	print_partition_stats(mod);
+    if (atoi(parameter) != 0) {
+        max_partitions = atoi(parameter);
+    }
+    setlinebuf(stdout);
+    /*open current io statistics file*/
+    iofp = fopen(IO_FILE, "r");
+    handle_error("Can't open /proc/diskstats", !iofp);
+    initialize();
+    get_kernel_stats();
+    print_partition_stats(mod);
 }
 
-static void set_io_record(struct module *mod, double st_array[],
-		U_64 pre_array[], U_64 cur_array[], int inter)
+static void
+set_io_record(struct module *mod, double st_array[],
+    U_64 pre_array[], U_64 cur_array[], int inter)
 {
-	int i;
-	for(i = 0; i < 11; i++){
-		if(cur_array[i] < pre_array[i]){
-			pre_array[i] = cur_array[i];
-		}
-	}
-	unsigned long long rd_ios = cur_array[0] - pre_array[0];
-	unsigned long long rd_merges = cur_array[1] - pre_array[1];
-	unsigned long long rd_sectors = cur_array[2] - pre_array[2];
-	unsigned long long rd_ticks = cur_array[3] - pre_array[3];;
-	unsigned long long wr_ios = cur_array[4] - pre_array[4];
-	unsigned long long wr_merges = cur_array[5] - pre_array[5];
-	unsigned long long wr_sectors = cur_array[6] - pre_array[6];
-	unsigned long long wr_ticks = cur_array[7] - pre_array[7];
-	unsigned long long ticks = cur_array[8] - pre_array[8];
-	unsigned long long aveq = cur_array[9] - pre_array[9];
-	double n_ios = rd_ios + wr_ios;
-	double n_ticks = rd_ticks + wr_ticks;
-	double n_kbytes = (rd_sectors + wr_sectors) / 2;
-	st_array[0] = rd_merges / (inter * 1.0);
-	st_array[1] = wr_merges / (inter * 1.0);
-	st_array[2] = rd_ios / (inter * 1.0);
-	st_array[3] = wr_ios / (inter * 1.0);
-	st_array[4] = rd_sectors / (inter * 2.0);
-	st_array[5] = wr_sectors / (inter * 2.0);
-	st_array[6] = n_ios ? n_kbytes / n_ios : 0.0;
-	st_array[7] = aveq / (inter * 1000);
-	st_array[8] = n_ios ? n_ticks / n_ios : 0.0;
-	st_array[9] = n_ios ? ticks / n_ios : 0.0;
-	st_array[10] = ticks / (inter * 10.0); /* percentage! */
-	if(st_array[10] > 100.0)
-		st_array[10] = 100.0;
+    int i, j;
+    for(i = 0; i < 11; i++){
+        if(cur_array[i] < pre_array[i]){
+            for(j = 0; j < 11; j++){
+                st_array[j] = -1;
+            }
+            return;
+        }
+    }
+    unsigned long long rd_ios = cur_array[0] - pre_array[0];
+    unsigned long long rd_merges = cur_array[1] - pre_array[1];
+    unsigned long long rd_sectors = cur_array[2] - pre_array[2];
+    unsigned long long rd_ticks = cur_array[3] - pre_array[3];;
+    unsigned long long wr_ios = cur_array[4] - pre_array[4];
+    unsigned long long wr_merges = cur_array[5] - pre_array[5];
+    unsigned long long wr_sectors = cur_array[6] - pre_array[6];
+    unsigned long long wr_ticks = cur_array[7] - pre_array[7];
+    unsigned long long ticks = cur_array[8] - pre_array[8];
+    unsigned long long aveq = cur_array[9] - pre_array[9];
+    double n_ios = rd_ios + wr_ios;
+    st_array[0] = rd_merges / (inter * 1.0);
+    st_array[1] = wr_merges / (inter * 1.0);
+    st_array[2] = rd_merges + rd_ios ? (double)rd_merges / (rd_merges + rd_ios) * 100 : 0.0;
+    st_array[3] = wr_merges + wr_ios ? (double)wr_merges / (wr_merges + wr_ios) * 100 : 0.0;
+    st_array[4] = rd_ios / (inter * 1.0);
+    st_array[5] = wr_ios / (inter * 1.0);
+    st_array[6] = rd_sectors / (inter * 1.0);
+    st_array[7] = wr_sectors / (inter * 1.0);
+    st_array[8] = n_ios ? (rd_sectors + wr_sectors) / (n_ios * 2) : 0.0;
+    st_array[9] = rd_ios ? rd_sectors / ((double)rd_ios * 2) : 0.0;
+    st_array[10] = wr_ios ? wr_sectors / ((double)wr_ios * 2) : 0.0;
+    st_array[11] = aveq / (inter * 1000);
+    st_array[12] = n_ios ? (rd_ticks + wr_ticks) / (double)n_ios : 0.0;
+    st_array[13] = rd_ios ? rd_ticks / (double)rd_ios : 0.0;
+    st_array[14] = wr_ios ? wr_ticks / (double)wr_ios : 0.0;
+    st_array[15] = n_ios ? ticks / n_ios : 0.0;
+    st_array[16] = ticks / (inter * 10.0); /* percentage! */
+    if(st_array[16] > 100.0)
+        st_array[16] = 100.0;
 }
-void mod_register(struct module *mod)
+
+void
+mod_register(struct module *mod)
 {
-	register_mod_fileds(mod, "--io", io_usage, io_info, 11, read_io_stat, set_io_record);
+    register_mod_fields(mod, "--io", io_usage, io_info, 17, read_io_stat, set_io_record);
 }
diff --git a/modules/mod_irq.c b/modules/mod_irq.c
deleted file mode 100644
index 949fa7c..0000000
--- a/modules/mod_irq.c
+++ /dev/null
@@ -1,300 +0,0 @@
-#include "public.h"
-
-#define IRQ_DETAIL_HDR "  intr"
-#define IRQ_STORE_FMT(d) "%lld"			
-#define IRQ_SUMMARY_HDR "intr/s"
-
-char * irq_usage = "    --irq               Interrupts statistics";
-
-/*
- * Structure for interrupts statistics.
- * In activity buffer: First structure is for total number of interrupts ("SUM").
- * Following structures are for each individual interrupt (0, 1, etc.)
- *
- * NOTE: The total number of interrupts is saved as a %llu by the kernel,
- * whereas individual interrupts are saved as %u.
- */
-struct __stats_irq {
-	unsigned long long irq_nr;
-};
-
-typedef struct __stats_irq (*stats_irq)[2];
-
-stats_irq s_st_irq;
-
-#define STATS_IRQ_SIZE  (sizeof(struct __stats_irq))
-
-union __irq_statistics{
-	struct irq_detail_statistics{
-		double intr;
-	} irq_detail, irq_summary;
-};
-
-#define MAXIRQ 128
-
-static union __irq_statistics irq_statistics[MAXIRQ][NR_ARRAY];
-
-#define IRQ_STRING_OPS(str, ops, fmt, stat, d)	\
-	ops(str, fmt,stat d irq_nr)
-
-
-#define SET_IRQ_STATISTICS(val, target, member, i)	\
-	__SET_MOD_STATISTICS				\
-(val.irq_detail.member,				\
- target[MEAN].irq_detail.member,		\
- target[MAX].irq_detail.member,			\
- target[MIN].irq_detail.member,			\
- (i))					
-
-static int f_init = FALSE;
-
-char word[12];				// reocrd the word read from textline
-char textline[256];			//record a line of text 
-unsigned char  text_index = 0;  //the index of textline above
-
-static void init_structure(int nr)
-{
-	s_st_irq = (stats_irq)
-		malloc(STATS_IRQ_SIZE * nr * 2);
-	if (s_st_irq == NULL)
-		do_debug(LOG_FATAL, "not enough memory!\n");
-}
-
-
-long stringToNum(char *string)
-{
-	long  temp = 0;
-	const char *ptr = string;
-
-	while(*string != '\0')
-	{
-		if ((*string < '0') || (*string > '9'))
-		{
-			break;
-		}
-		temp = temp * 10 + (*string - '0');
-		string++;
-	}
-	if (*ptr == '-')
-	{
-		temp = -temp;
-	}
-	return temp;
-}
-
-void  getword(char *textline)
-{       int i;
-
-	i = 0;
-	for(; isspace(textline[text_index]); text_index++)
-		;
-	for(; !isspace(textline[text_index]); i++, text_index++){
-		word[i] = textline[text_index];
-	}
-
-	word[i]= '\0';
-}
-
-
-int countCPUNumber()   /*the number of word is equal to the number of processor*/
-{
-	int in = 0;
-	int cpu_number = 0;
-	//      printf("string length is %d", strlen(textline));
-	for(; textline[text_index] != '\0'; text_index++){
-		if(isalnum(textline[text_index]) && in == 0){
-			in = 1;
-			cpu_number++;
-		}
-		else if(isspace(textline[text_index])){
-			in = 0;
-		}
-	}
-	return cpu_number;
-}
-
-/*
- ***************************************************************************
- * Count number of interrupts that are in /proc/stat file.
- *
- * RETURNS:
- * Number of interrupts, including total number of interrupts.
- ***************************************************************************
- */
-static int count_irq_nr(char *record)
-{
-	FILE *fp;
-	char line[256];
-	char i;int n=0;
-	int sw = TRUE;
-	if ((fp = fopen(INTERRUPT, "r")) == NULL)
-		return 0;
-	while (fgets(line, 256, fp) != NULL) {
-		if(!sw) {
-			sscanf(line, "%*c%*c%c:", &i);
-			if (i >= '0' && i <= '9')
-				n++;
-			else
-				continue;
-		} else sw = FALSE;
-	}
-	fclose(fp);
-	return n;
-}
-
-
-void read_irq_stat(struct module *mod, int data_type)
-{
-	char buf[MAX_LINE_LEN];
-	FILE *fp;
-	int i, pos = 0;
-	int cpu_nr;
-	int inter_num;
-	unsigned long long inter_sum;
-
-	fp = fopen(INTERRUPT, "r");
-
-	if(fp == NULL){
-		perror("unable to open file /proc/interrupts");
-		exit(-1);
-	}
-
-	fgets(textline, 256, fp);
-
-	cpu_nr = countCPUNumber();
-
-	while(fgets(textline, MAX_LINE_LEN, fp) != NULL){
-		text_index = 0;
-		getword(textline);
-		if(isalpha(*word)){
-			continue;
-		}
-		inter_num = (int)stringToNum(word);
-		inter_sum = 0;
-		for(i = 0; i!= cpu_nr; i++){
-			getword(textline);
-			inter_sum += stringToNum(word);
-		}
-		pos += sprintf(buf + pos, "in%d=%lld;", inter_num, inter_sum);
-	}
-	fclose(fp);
-	buf[pos] = '\0';
-	mod->detail = strdup(buf);
-}
-
-
-void __irq_ops(char *_detail_last,
-		char *_detail_curr,
-		int dtype, int otype,
-		stats_irq si,
-		char *_buf, int *pos,
-		unsigned long itv,
-		unsigned int idx)
-{
-	union __irq_statistics tmp;
-	int len = 0;
-	IRQ_STRING_OPS(_detail_curr, sscanf,
-			IRQ_STORE_FMT(DATA_SPLIT), &(*si)[0], .);
-	IRQ_STRING_OPS(_detail_last, sscanf,
-			IRQ_STORE_FMT(DATA_SPLIT), &(*si)[1], .);
-
-	__COMPUTE_MOD_VALUE(tmp.irq_detail.intr, S_VALUE,
-			(*si)[1].irq_nr, (*si)[0].irq_nr, itv);
-
-	SET_IRQ_STATISTICS(tmp, irq_statistics[idx], intr, itv);
-
-	if (dtype == DATA_DETAIL) {
-		/* write each record to buffer */
-		PRINT(_buf + len,tmp.irq_detail.intr , len, otype);
-	}
-	else if (dtype == DATA_SUMMARY)	{
-		PRINT(_buf + len, tmp.irq_detail.intr, len, otype);
-	}
-	*pos += len - 1 ;
-}
-
-
-char *irq_ops(char *last_record,
-		char *curr_record,
-		time_t last_time,
-		time_t curr_time,
-		int data_type, 
-		int output_type)
-{
-	unsigned long itv;
-	char buf[MAX_LINE_LEN];
-	int pos = 0;
-	unsigned int i = 0;
-	/* if statistic structure is not inited, 
-	   we will alloc space here */
-	int nr = count_irq_nr(last_record);
-	if (!f_init) {
-		init_structure(nr);
-		f_init = TRUE;
-	}
-
-	CALITV(last_time, curr_time, itv);
-
-	stats_irq temp_si = s_st_irq;
-
-	char last_mnt[MAX_STRING_LEN] = {0};
-	char curr_mnt[MAX_STRING_LEN] = {0};
-
-	if(*last_record == '\0') {
-		/* first record */
-	}
-	else {
-		while((last_record = getitem(last_record, last_mnt)) != NULL &&
-				(curr_record = getitem(curr_record, curr_mnt)) != NULL) {
-
-			__irq_ops(last_mnt , curr_mnt,
-					data_type, output_type,
-					temp_si, buf + pos, &pos, itv, i);
-			i++;
-			temp_si++;
-			memset(last_mnt, '0', MAX_STRING_LEN);
-			memset(curr_mnt, '0', MAX_STRING_LEN);
-		}
-	}
-
-
-	buf[pos] = '\0';
-	return(strdup(buf));
-}
-
-static char **get_avg(int data_type, int count)
-{
-	char **statis;
-	int pos[3] = {0, 0, 0};
-	int i, j;
-	INIT_STRING_P(statis, 3, MAX_STRING_LEN);
-	int nr = count_irq_nr(NULL);
-
-	for(j = 0; j < nr; j++) {
-		for(i = 0; i < 3; i++) { 
-			if (data_type == DATA_DETAIL) {
-				__PRINT_AVG(statis, pos, irq_statistics[j], irq_detail.intr, i, count, OUTPUT_PRINT); 
-			}
-			else if (data_type == DATA_SUMMARY) {
-				/* __PRINT_AVG(statis, pos, irq_statistics[j], irq_summary.kutil, i, count, OUTPUT_PRINT); */
-			}
-			pos[i] -= 1;
-		}
-	}
-	return statis;
-}
-
-void mod_register(struct module *mod)
-{
-	sprintf(mod->detail_hdr, IRQ_DETAIL_HDR);
-	sprintf(mod->summary_hdr, IRQ_SUMMARY_HDR);
-	mod->usage = irq_usage;
-	sprintf(mod->opt_line, "--irq");
-	mod->data_collect = read_irq_stat;
-	mod->data_operation = irq_ops;
-	mod->show_avg = get_avg;
-	mod->mod_free = func_mod_free;
-}
-
-
-
diff --git a/modules/mod_ktables.c b/modules/mod_ktables.c
deleted file mode 100644
index 0be451e..0000000
--- a/modules/mod_ktables.c
+++ /dev/null
@@ -1,176 +0,0 @@
-#include "public.h"
-
-#define KTABLES_DETAIL_HDR(d)			\
-	" fused"d" iused"d" dstat"d" pytnr"
-
-#define KTABLES_STORE_FMT(d)			\
-	"%d"d"%d"d"%d"d"%d"
-
-#define KTABLES_DETAIL_FMT(d)			\
-	"%d"d"%d"d"%d"d"%d"
-
-#define KTABLES_SUMMARY_FMT			\
-	KTABLES_DETAIL_FMT
-
-#define KTABLES_SUMMARY_HDR			\
-	KTABLES_DETAIL_HDR
-
-char *ktables_usage = "    --ktables           Kernel table statistics";
-
-/* Structure for kernel tables statistics */
-struct stats_ktables {
-	unsigned int  file_used;
-	unsigned int  inode_used;
-	unsigned int  dentry_stat;
-	unsigned int  pty_nr;
-} s_st_ktables[2];
-
-#define STATS_KTABLES_SIZE      (sizeof(struct stats_ktables))
-
-#define KTABLES_STRING_OPS(str, ops, fmt, stat, d)	\
-	ops(str, fmt,					\
-			stat d file_used,				\
-			stat d inode_used,				\
-			stat d dentry_stat,				\
-			stat d pty_nr)
-
-union ktables_statistics {
-	struct ktables_detail_statistics
-	{
-		double fused;
-		double iused;
-		double dstat;
-		double ptynr;
-	}ktables_detail, ktbales_summary;
-} ktables_statis[NR_ARRAY];
-
-//extern unsigned long itv, oitv;
-
-/*
- *********************************************************
- *Read kernel tables statistics from various system files.
- *********************************************************
- */
-void read_kernel_tables(struct module *mod, int data_type)
-{
-	char buf[MAX_LINE_LEN];
-	FILE *fp;
-	unsigned int parm;
-	myalloc(st_ktables, stats_ktables, STATS_KTABLES_SIZE);
-
-	/* Open /proc/sys/fs/dentry-state file */
-	if ((fp = fopen(FDENTRY_STATE, "r")) != NULL) {
-		fscanf(fp, "%*d %u",
-				&st_ktables->dentry_stat);
-		fclose(fp);
-	}
-
-	/* Open /proc/sys/fs/file-nr file */
-	if ((fp = fopen(FFILE_NR, "r")) != NULL) {
-		fscanf(fp, "%u %u",
-				&st_ktables->file_used, &parm);
-		fclose(fp);
-		/*
-		 * The number of used handles is the number of allocated ones
-		 * minus the number of free ones.
-		 */
-		st_ktables->file_used -= parm;
-	}
-
-	/* Open /proc/sys/fs/inode-state file */
-	if ((fp = fopen(FINODE_STATE, "r")) != NULL) {
-		fscanf(fp, "%u %u",
-				&st_ktables->inode_used, &parm);
-		fclose(fp);
-		/*
-		 * The number of inuse inodes is the number of allocated ones
-		 * minus the number of free ones.
-		 */
-		st_ktables->inode_used -= parm;
-	}
-
-	/* Open /proc/sys/kernel/pty/nr file */
-	if ((fp = fopen(PTY_NR, "r")) != NULL) {
-		fscanf(fp, "%u",
-				&st_ktables->pty_nr);
-		fclose(fp);
-	}
-	int pos = KTABLES_STRING_OPS(buf, sprintf, 
-			KTABLES_STORE_FMT(DATA_SPLIT), st_ktables, ->);
-	buf[pos] = '\0';
-	mod->detail = strdup(buf);
-}
-
-static char **get_avg(int data_type, int count)
-{
-	char **s_ktables;
-	int pos[3] = {0, 0, 0};
-	int i;
-	INIT_STRING_P(s_ktables, 3, MAX_STRING_LEN);
-	for(i = 0; i < 3; i++) {
-		__PRINT_AVG(s_ktables, pos, ktables_statis, ktables_detail.fused, i, count, OUTPUT_PRINT);
-		__PRINT_AVG(s_ktables, pos, ktables_statis, ktables_detail.iused, i, count, OUTPUT_PRINT);
-		__PRINT_AVG(s_ktables, pos, ktables_statis, ktables_detail.dstat, i, count, OUTPUT_PRINT);
-		__PRINT_AVG(s_ktables, pos, ktables_statis, ktables_detail.ptynr, i, count, OUTPUT_PRINT);
-	}
-	return s_ktables;
-}
-
-char *ktables_ops(char *last_record,
-		char *curr_record,
-		time_t last_time,
-		time_t curr_time,
-		int data_type,
-		int output_type)
-{
-	char buf[MAX_STRING_LEN];
-	unsigned long itv;
-
-	CALITV(last_time, curr_time, itv);
-
-	KTABLES_STRING_OPS(last_record, sscanf, 
-			KTABLES_STORE_FMT(DATA_SPLIT), &s_st_ktables[1], .);
-
-	KTABLES_STRING_OPS(curr_record, sscanf, 
-			KTABLES_STORE_FMT(DATA_SPLIT), &s_st_ktables[0], .);
-
-	DECLARE_TMP_MOD_STATISTICS(ktables);
-
-	if (data_type == DATA_DETAIL || data_type == DATA_SUMMARY) {
-		SET_CURRENT_VALUE(ktables, detail, file_used, fused);
-		SET_CURRENT_VALUE(ktables, detail, inode_used, iused);
-		SET_CURRENT_VALUE(ktables, detail, dentry_stat, dstat);
-		SET_CURRENT_VALUE(ktables, detail, pty_nr, ptynr);
-	}
-
-	if(data_type == DATA_DETAIL || data_type == DATA_SUMMARY) {
-		SET_MOD_STATISTICS(ktables, fused, itv, detail);
-		SET_MOD_STATISTICS(ktables, iused, itv, detail);
-		SET_MOD_STATISTICS(ktables, dstat, itv, detail);
-		SET_MOD_STATISTICS(ktables, ptynr, itv, detail);
-
-		int pos = 0;
-		PRINT(buf + pos, ktables_tmp_s.ktables_detail.fused, pos, output_type);
-		PRINT(buf + pos, ktables_tmp_s.ktables_detail.iused, pos, output_type);
-		PRINT(buf + pos, ktables_tmp_s.ktables_detail.dstat, pos, output_type);
-		PRINT(buf + pos, ktables_tmp_s.ktables_detail.ptynr, pos, output_type);
-
-		buf[pos - 1] = '\0';
-
-	}
-
-	return(strdup(buf));
-}
-
-void mod_register(struct module *mod)
-{
-	sprintf(mod->detail_hdr, KTABLES_DETAIL_HDR(" "));
-	sprintf(mod->summary_hdr, KTABLES_SUMMARY_HDR(" "));
-	mod->usage = ktables_usage;
-	sprintf(mod->opt_line, "--ktables");
-	mod->data_collect = read_kernel_tables;
-	mod->data_operation = ktables_ops;
-	mod->show_avg = get_avg;
-	mod->mod_free = func_mod_free;
-}
-
diff --git a/modules/mod_load.c b/modules/mod_load.c
index ea6da8c..d66bae3 100644
--- a/modules/mod_load.c
+++ b/modules/mod_load.c
@@ -1,87 +1,92 @@
 #include "tsar.h"
 
-#define LOAD_DETAIL_HDR(d)			\
-	"  runq"d" plist"d"  min1"d		\
+#define LOAD_DETAIL_HDR(d)          \
+    "  runq"d" plist"d"  min1"d     \
 "  min5"d" min15"
 
-#define LOAD_STORE_FMT(d)			\
-	"%ld"d"%d"d"%d"d"%d"d"%d"
+#define LOAD_STORE_FMT(d)           \
+    "%ld"d"%d"d"%d"d"%d"d"%d"
 
 char *load_usage = "    --load              System Run Queue and load average";
 
 /* Structure for queue and load statistics */
 struct stats_load {
-	unsigned long nr_running;
-	unsigned int  load_avg_1;
-	unsigned int  load_avg_5;
-	unsigned int  load_avg_15;
-	unsigned int  nr_threads;
+    unsigned long nr_running;
+    unsigned int  load_avg_1;
+    unsigned int  load_avg_5;
+    unsigned int  load_avg_15;
+    unsigned int  nr_threads;
 };
 
-#define STATS_LOAD_SIZE	(sizeof(struct stats_load))
+#define STATS_LOAD_SIZE (sizeof(struct stats_load))
 
-void read_stat_load(struct module *mod)
+void
+read_stat_load(struct module *mod)
 {
-	FILE *fp;
-	char buf[LEN_4096];
-	memset(buf, 0, LEN_4096);
-	int load_tmp[3];
-	struct stats_load st_load;
-	memset(&st_load, 0, sizeof(struct stats_load));
+    int     load_tmp[3];
+    FILE   *fp;
+    char    buf[LEN_4096];
+    struct  stats_load st_load;
+    memset(buf, 0, LEN_4096);
+    memset(&st_load, 0, sizeof(struct stats_load));
 
-	if ((fp = fopen(LOADAVG, "r")) == NULL) {
-		return;
-	}
+    if ((fp = fopen(LOADAVG, "r")) == NULL) {
+        return;
+    }
 
-	/* Read load averages and queue length */
-	fscanf(fp, "%d.%d %d.%d %d.%d %ld/%d %*d\n",
-			&load_tmp[0], &st_load.load_avg_1,
-			&load_tmp[1], &st_load.load_avg_5,
-			&load_tmp[2], &st_load.load_avg_15,
-			&st_load.nr_running,
-			&st_load.nr_threads);
+    /* Read load averages and queue length */
+    if (fscanf(fp, "%d.%d %d.%d %d.%d %ld/%d %*d\n",
+            &load_tmp[0], &st_load.load_avg_1,
+            &load_tmp[1], &st_load.load_avg_5,
+            &load_tmp[2], &st_load.load_avg_15,
+            &st_load.nr_running,
+            &st_load.nr_threads) != 8)
+    {
+        fclose(fp);
+        return;
+    }
+    st_load.load_avg_1  += load_tmp[0] * 100;
+    st_load.load_avg_5  += load_tmp[1] * 100;
+    st_load.load_avg_15 += load_tmp[2] * 100;
 
-	st_load.load_avg_1  += load_tmp[0] * 100;
-	st_load.load_avg_5  += load_tmp[1] * 100;
-	st_load.load_avg_15 += load_tmp[2] * 100;
+    if (st_load.nr_running) {
+        /* Do not take current process into account */
+        st_load.nr_running--;
+    }
 
-	if (st_load.nr_running) {
-		/* Do not take current process into account */
-		st_load.nr_running--;
-	}
-
-	int pos = sprintf(buf , "%u,%u,%u,%lu,%u",
-			st_load.load_avg_1,
-			st_load.load_avg_5,
-			st_load.load_avg_15,
-			st_load.nr_running,
-			st_load.nr_threads);
-	buf[pos] = '\0';
-	set_mod_record(mod, buf);
-	fclose(fp);
+    sprintf(buf , "%u,%u,%u,%lu,%u",
+            st_load.load_avg_1,
+            st_load.load_avg_5,
+            st_load.load_avg_15,
+            st_load.nr_running,
+            st_load.nr_threads);
+    set_mod_record(mod, buf);
+    fclose(fp);
 }
 
-static void set_load_record(struct module *mod, double st_array[],
-		U_64 pre_array[], U_64 cur_array[], int inter)
+static void
+set_load_record(struct module *mod, double st_array[],
+    U_64 pre_array[], U_64 cur_array[], int inter)
 {
-	int i;
-	for (i = 0; i < 3; i++) {
-		st_array[i] = cur_array[i] /100.0;
-	}
-	st_array[3] = cur_array[3];
-	st_array[4] = cur_array[4];
+    int i;
+    for (i = 0; i < 3; i++) {
+        st_array[i] = cur_array[i] / 100.0;
+    }
+    st_array[3] = cur_array[3];
+    st_array[4] = cur_array[4];
 }
 
 static struct mod_info load_info[] = {
-	{" load1", SUMMARY_BIT,  0,  STATS_NULL},
-	{" load5", DETAIL_BIT,  0,  STATS_NULL},
-	{"load15", DETAIL_BIT,  0,  STATS_NULL},
-	{"  runq", DETAIL_BIT,  0,  STATS_NULL},
-	{"  plit", DETAIL_BIT,  0,  STATS_NULL}
+    {" load1", SUMMARY_BIT,  0,  STATS_NULL},
+    {" load5", DETAIL_BIT,  0,  STATS_NULL},
+    {"load15", DETAIL_BIT,  0,  STATS_NULL},
+    {"  runq", DETAIL_BIT,  0,  STATS_NULL},
+    {"  plit", DETAIL_BIT,  0,  STATS_NULL}
 };
 
-void mod_register(struct module *mod)
+void
+mod_register(struct module *mod)
 {
-	register_mod_fileds(mod, "--load", load_usage, load_info, 5, read_stat_load, set_load_record);
+    register_mod_fields(mod, "--load", load_usage, load_info, 5, read_stat_load, set_load_record);
 }
 
diff --git a/modules/mod_lvs.c b/modules/mod_lvs.c
index 46d6d45..a008b26 100644
--- a/modules/mod_lvs.c
+++ b/modules/mod_lvs.c
@@ -1,80 +1,231 @@
-#define   _GNU_SOURCE
-#include "tsar.h"
-//#include <time.h>
-//#include <sys/stat.h>
-
-#define LVS_STATS "/proc/net/ip_vs_stats"
-#define KEEPALIVE "/var/run/keepalived.pid"
-//#define LVS_STATS "/home/like/ip_vs_stats"
-#define LVS_STORE_FMT(d)			\
-	"%ld"d"%ld"d"%ld"d"%ld"d"%ld"d"%ld"
-#define MAX_LINE_LEN 1024
-struct stats_lvs{   
-	unsigned long stat;
-	unsigned long conns;
-	unsigned long pktin;
-	unsigned long pktout;
-	unsigned long bytin;
-	unsigned long bytout;
-};
-#define STATS_LVS_SIZE       (sizeof(struct stats_lvs))
-
-static struct mod_info info[] = {
-	{"  stat", DETAIL_BIT,  MERGE_NULL,  STATS_NULL},
-	{" conns", SUMMARY_BIT,  MERGE_NULL,  STATS_NULL},
-	{" pktin", DETAIL_BIT,  MERGE_NULL,  STATS_NULL},
-	{"pktout", DETAIL_BIT,  MERGE_NULL,  STATS_NULL},
-	{" bytin", DETAIL_BIT,  MERGE_NULL,  STATS_NULL},
-	{"bytout", DETAIL_BIT,  MERGE_NULL,  STATS_NULL}
-};
-
-static char *lvs_usage = "    --lvs               lvs connections and packets and bytes in/out";
-struct stats_lvs st_lvs;
-/*
- *******************************************************
- * Read swapping statistics from ip_vs_stat
- *******************************************************
- */
-static void read_lvs(struct module *mod)
-{
-	st_lvs.stat = 0;
-	st_lvs.conns = 0;
-	st_lvs.pktin = 0;
-	st_lvs.pktout = 0;
-	st_lvs.bytin = 0;
-	st_lvs.bytout = 0;
-	char buf[512];
-	int i=0,pos=0;
-	FILE *fp;
-	//struct stat statbuf;
-	char line[MAX_LINE_LEN];
-	if(access(KEEPALIVE,0) == 0)
-	{
-		if ((fp = fopen(LVS_STATS, "r")) != NULL)
-		{   
-			while (fgets(line, MAX_LINE_LEN, fp) != NULL) {
-				i++;
-				if (i == 6) {
-					sscanf(line, "%lx %lx %lx %lx %lx", &st_lvs.conns, &st_lvs.pktin, &st_lvs.pktout,&st_lvs.bytin,&st_lvs.bytout);
-				}   
-				st_lvs.stat = 1;
-			}
-			fclose(fp);
-		}
-	}
-	//fstat(fileno(fp), &statbuf);
-	//printf( "Time   file   last   opened:   %s\n ", ctime(&statbuf.st_ctime));
-	//printf(LVS_STORE_FMT(DATA_SPLIT),st_lvs.stat,st_lvs.conns,st_lvs.pktin,st_lvs.pktout,st_lvs.bytin,st_lvs.bytout);
-	if(st_lvs.stat == 1){
-		pos = sprintf(buf, LVS_STORE_FMT(DATA_SPLIT), st_lvs.stat, st_lvs.conns, st_lvs.pktin, st_lvs.pktout, st_lvs.bytin, st_lvs.bytout);
-	}
-	buf[pos] = '\0';
-	set_mod_record(mod, buf);
-	return;
-}
-
-void mod_register(struct module *mod)
-{
-	register_mod_fileds(mod, "--lvs", lvs_usage, info, sizeof(info)/sizeof(struct mod_info), read_lvs, NULL);
-}
-
+#define   _GNU_SOURCE
+#include "tsar.h"
+
+#define LVS_PROC_STATS 	"/proc/net/ip_vs_stats"
+#define LVS_CONN_PROC_STATS	"/proc/net/ip_vs_conn_stats"
+
+#define LVS_CMD			"sudo /usr/local/sbin/slb_admin -ln --total --dump"
+#define LVS_CONN_CMD	"sudo /usr/local/sbin/appctl -csa"
+
+#define LVS_CMD_PATH	"/usr/local/sbin/slb_admin"
+#define LVS_STORE_FMT(d)            \
+	"%lld"d"%lld"d"%lld"d"%lld"d"%lld"d"%lld"d\
+	"%lld"d"%lld"d"%lld"d"%lld"d"%lld"d"%lld"d"%lld"d"%lld"
+#define MAX_LINE_LEN 1024
+struct stats_lvs{
+	unsigned long long stat;
+	unsigned long long conns;
+	unsigned long long pktin;
+	unsigned long long pktout;
+	unsigned long long bytin;
+	unsigned long long bytout;
+
+	unsigned long long total_conns;		/* total conns */
+	unsigned long long local_conns;		/* local conns */
+	unsigned long long act_conns;		/* active conns */
+	unsigned long long inact_conns;		/* inactive conns */
+	unsigned long long sync_conns;		/* sync conns */
+	unsigned long long sync_act_conns;	/* sync active conns */
+	unsigned long long sync_inact_conns;	/* sync inactive conns */
+	unsigned long long template_conns;	/* template conns */
+};
+#define STATS_LVS_SIZE       (sizeof(struct stats_lvs))
+
+static struct mod_info info[] = {
+	{"  stat", DETAIL_BIT,  MERGE_NULL,  STATS_NULL},
+	{" conns", SUMMARY_BIT,  MERGE_NULL,  STATS_SUB_INTER},
+	{" pktin", DETAIL_BIT,  MERGE_NULL,  STATS_SUB_INTER},
+	{"pktout", DETAIL_BIT,  MERGE_NULL,  STATS_SUB_INTER},
+	{" bytin", DETAIL_BIT,  MERGE_NULL,  STATS_SUB_INTER},
+	{"bytout", DETAIL_BIT,  MERGE_NULL,  STATS_SUB_INTER},
+	{" total", DETAIL_BIT,  MERGE_NULL,  STATS_NULL},
+	{" local", DETAIL_BIT,  MERGE_NULL,  STATS_NULL},
+	{"  lact", DETAIL_BIT,  MERGE_NULL,  STATS_NULL},
+	{"linact", DETAIL_BIT,  MERGE_NULL,  STATS_NULL},
+	{"  sync", DETAIL_BIT,  MERGE_NULL,  STATS_NULL},
+	{"  sact", DETAIL_BIT,  MERGE_NULL,  STATS_NULL},
+	{"sinact", DETAIL_BIT,  MERGE_NULL,  STATS_NULL},
+	{" templ", DETAIL_BIT,  MERGE_NULL,  STATS_NULL},
+};
+
+static char *lvs_usage = "    --lvs               lvs connections and packets and bytes in/out";
+struct stats_lvs st_lvs;
+/*
+ *******************************************************
+ * Read swapping statistics from ip_vs_stat
+ *******************************************************
+ */
+static void
+read_lvs_stat(int has_netframe)
+{
+	int    i = 0, use_popen = 0;
+	char   tmp[5][16];
+	FILE  *fp = NULL;
+	char   line[MAX_LINE_LEN];
+
+	if (has_netframe) {
+		fp = popen(LVS_CMD, "r");
+		use_popen = 1;
+	} else if (!access(LVS_PROC_STATS, F_OK))
+		fp = fopen(LVS_PROC_STATS, "r");
+
+	if (!fp)
+		return;
+
+	st_lvs.stat = 1;
+	while (fgets(line, MAX_LINE_LEN, fp) != NULL) {
+		i++;
+		if (i < 3) {
+			continue;
+		}
+		if (!strncmp(line, "CPU", 3)) {
+			/* CPU 0:       5462458943          44712664864          54084995692        8542115117674       41738811918899 */
+			int    k = 0;
+			k = strcspn(line, ":");
+			sscanf(line + k + 1, "%s %s %s %s %s", tmp[0], tmp[1], tmp[2], tmp[3], tmp[4]);
+			st_lvs.conns += strtoll(tmp[0], NULL, 10);
+			st_lvs.pktin += strtoll(tmp[1], NULL, 10);
+			st_lvs.pktout += strtoll(tmp[2], NULL, 10);
+			st_lvs.bytin += strtoll(tmp[3], NULL, 10);
+			st_lvs.bytout += strtoll(tmp[4], NULL, 10);
+		} else {
+			/* 218EEA1A 1B3BA96D        0    163142140FA1F                0 */
+			sscanf(line, "%s %s %s %s %s", tmp[0], tmp[1], tmp[2], tmp[3], tmp[4]);
+			st_lvs.conns += strtoll(tmp[0], NULL ,16);
+			st_lvs.pktin += strtoll(tmp[1], NULL, 16);
+			st_lvs.pktout += strtoll(tmp[2], NULL, 16);
+			st_lvs.bytin += strtoll(tmp[3], NULL, 16);
+			st_lvs.bytout += strtoll(tmp[4], NULL, 16);
+			break;
+		}
+	}
+
+	if (use_popen)
+		pclose(fp);
+	else
+		fclose(fp);
+}
+
+static void
+read_lvs_conn_stat(int has_netframe)
+{
+	int use_popen = 0;
+	FILE *fp = NULL;
+	char line[MAX_LINE_LEN];
+
+	if (has_netframe) {
+		fp = popen(LVS_CONN_CMD, "r");
+		use_popen = 1;
+	} else if (!access(LVS_CONN_PROC_STATS, F_OK))
+		fp = fopen(LVS_CONN_PROC_STATS, "r");
+
+	if (!fp)
+		return;
+
+	while (fgets(line, MAX_LINE_LEN, fp) != NULL) {
+
+		if (has_netframe) {
+			unsigned long long *item = NULL;
+
+			/* Example:
+			total_conns                              :  0
+			local_conns                              :  0
+			local_active_conns                       :  0
+			local_inactive_conns                     :  0
+			sync_conns                               :  0
+			sync_active_conns                        :  0
+			sync_inactive_conns                      :  0
+			template_conns                           :  0
+			*/
+			if (!strncmp(line, "total_conns", 11))
+				item = &st_lvs.total_conns;
+			else if (!strncmp(line, "local_conns", 11))
+				item = &st_lvs.local_conns;
+			else if (!strncmp(line, "local_active_conns", 18))
+				item = &st_lvs.act_conns;
+			else if (!strncmp(line, "local_inactive_conns", 20))
+				item = &st_lvs.inact_conns;
+			else if (!strncmp(line, "sync_conns", 10))
+				item = &st_lvs.sync_conns;
+			else if (!strncmp(line, "sync_active_conns", 16))
+				item = &st_lvs.sync_act_conns;
+			else if (!strncmp(line, "sync_inactive_conns", 18))
+				item = &st_lvs.sync_inact_conns;
+			else if (!strncmp(line, "template_conns", 10))
+				item = &st_lvs.template_conns;
+
+			if (item)
+				*item = strtoll(strchr(line, ':') + 1, NULL, 10);
+
+		} else {
+			/* Example:
+			PersistConns: 17
+
+			Total     Local     Sync      LocAct    SynAct    LocInAct  SynInAct  Flush     Flush
+			Conns     Conns     Conns     Conns     Conns     Conns     Conns     Threshold State
+			CPU0 : 58094     14710     43384     9522      28133     5188      15251     0         N/A
+			CPU11: 49888     12589     37299     7657      22498     4932      14801     0         N/A
+			TOTAL: 603642    151514    452128    90610     269578    60904     182550    0         N/A
+			*/
+			if (!strncmp(line, "PersistConns", 12)) {
+				st_lvs.template_conns = strtoll(strchr(line, ':') + 1, NULL, 10);
+			} else if (!strncmp(line, "TOTAL", 5)) {
+				char tmp[7][16];
+
+				sscanf(strchr(line, ':') + 1, "%s %s %s %s %s %s %s",
+						tmp[0], tmp[1], tmp[2], tmp[3], tmp[4], tmp[5], tmp[6]);
+
+				st_lvs.total_conns = strtoll(tmp[0], NULL, 10);
+				st_lvs.local_conns = strtoll(tmp[1], NULL, 10);
+				st_lvs.sync_conns = strtoll(tmp[2], NULL, 10);
+				st_lvs.act_conns = strtoll(tmp[3], NULL, 10);
+				st_lvs.sync_act_conns = strtoll(tmp[4], NULL, 10);
+				st_lvs.inact_conns = strtoll(tmp[5], NULL, 10);
+				st_lvs.sync_inact_conns = strtoll(tmp[6], NULL, 10);
+			}
+		}
+	}
+
+	if (use_popen)
+		pclose(fp);
+	else
+		fclose(fp);
+}
+
+static void
+read_lvs(struct module *mod)
+{
+	char buf[512] = { 0 };
+	int pos = 0, has_netframe = 0;
+
+	memset(&st_lvs, 0, sizeof(struct stats_lvs));
+
+	if (!access(LVS_CMD_PATH, F_OK | X_OK))
+		has_netframe = 1;
+
+	read_lvs_stat(has_netframe);
+
+	read_lvs_conn_stat(has_netframe);
+
+	if (st_lvs.stat == 1) {
+		pos = sprintf(buf, LVS_STORE_FMT(DATA_SPLIT),
+				st_lvs.stat, st_lvs.conns,
+				st_lvs.pktin, st_lvs.pktout, st_lvs.bytin, st_lvs.bytout,
+				st_lvs.total_conns, st_lvs.local_conns, st_lvs.act_conns, st_lvs.inact_conns,
+				st_lvs.sync_conns, st_lvs.sync_act_conns, st_lvs.sync_inact_conns,
+				st_lvs.template_conns);
+	} else {
+		return;
+	}
+
+	buf[pos] = '\0';
+	set_mod_record(mod, buf);
+	return;
+}
+
+
+void
+mod_register(struct module *mod)
+{
+	register_mod_fields(mod, "--lvs", lvs_usage, info, sizeof(info)/sizeof(struct mod_info), read_lvs, NULL);
+}
diff --git a/modules/mod_mem.c b/modules/mod_mem.c
index 22241e6..c8fbef2 100644
--- a/modules/mod_mem.c
+++ b/modules/mod_mem.c
@@ -5,112 +5,122 @@ char *mem_usage =
 
 /* Structure for memory and swap space utilization statistics */
 struct stats_mem {
-	unsigned long frmkb;
-	unsigned long bufkb;
-	unsigned long camkb;
-	unsigned long tlmkb;
-	unsigned long acmkb;
-	unsigned long iamkb;
-	unsigned long slmkb;
-	unsigned long frskb;
-	unsigned long tlskb; 
-	unsigned long caskb;
-	unsigned long comkb;
+    unsigned long frmkb;
+    unsigned long bufkb;
+    unsigned long camkb;
+    unsigned long tlmkb;
+    unsigned long acmkb;
+    unsigned long iamkb;
+    unsigned long slmkb;
+    unsigned long frskb;
+    unsigned long tlskb;
+    unsigned long caskb;
+    unsigned long comkb;
 };
 
-static void read_mem_stats(struct module *mod)
+static void
+read_mem_stats(struct module *mod)
 {
-	FILE *fp;
-	char line[LEN_128];
-	char buf[LEN_4096];
-	memset(buf, 0, LEN_4096);
-	struct stats_mem st_mem;
-	memset(&st_mem, 0, sizeof(struct stats_mem));
-	if ((fp = fopen(MEMINFO, "r")) == NULL) {
-		return;
-	}
+    FILE             *fp;
+    char              line[LEN_128];
+    char              buf[LEN_4096];
+    struct stats_mem  st_mem;
 
-	while (fgets(line, 128, fp) != NULL) {
+    memset(buf, 0, LEN_4096);
+    memset(&st_mem, 0, sizeof(struct stats_mem));
+    if ((fp = fopen(MEMINFO, "r")) == NULL) {
+        return;
+    }
 
-		if (!strncmp(line, "MemTotal:", 9)) {
-			/* Read the total amount of memory in kB */
-			sscanf(line + 9, "%lu", &st_mem.tlmkb);
-		}
-		else if (!strncmp(line, "MemFree:", 8)) {
-			/* Read the amount of free memory in kB */
-			sscanf(line + 8, "%lu", &st_mem.frmkb);
-		}
-		else if (!strncmp(line, "Buffers:", 8)) {
-			/* Read the amount of buffered memory in kB */
-			sscanf(line + 8, "%lu", &st_mem.bufkb);
-		}
-		else if (!strncmp(line, "Cached:", 7)) {
-			/* Read the amount of cached memory in kB */
-			sscanf(line + 7, "%lu", &st_mem.camkb);
-		}
-		else if (!strncmp(line, "Active:", 7)) {
-			/* Read the amount of Active memory in kB */
-			sscanf(line + 7, "%lu", &st_mem.acmkb);
-		}
-		else if (!strncmp(line, "Inactive:", 9)) {
-			/* Read the amount of Inactive memory in kB */
-			sscanf(line + 9, "%lu", &st_mem.iamkb);
-		}
-		else if (!strncmp(line, "Slab:", 5)) {
-			/* Read the amount of Slab memory in kB */
-			sscanf(line + 5, "%lu", &st_mem.slmkb);
-		}
-		else if (!strncmp(line, "SwapCached:", 11)) {
-			/* Read the amount of cached swap in kB */
-			sscanf(line + 11, "%lu", &st_mem.caskb);
-		}
-		else if (!strncmp(line, "SwapTotal:", 10)) {
-			/* Read the total amount of swap memory in kB */
-			sscanf(line + 10, "%lu", &st_mem.tlskb);
-		}
-		else if (!strncmp(line, "SwapFree:", 9)) {
-			/* Read the amount of free swap memory in kB */
-			sscanf(line + 9, "%lu", &st_mem.frskb);
-		}
-		else if (!strncmp(line, "Committed_AS:", 13)) {
-			/* Read the amount of commited memory in kB */
-			sscanf(line + 13, "%lu", &st_mem.comkb);
-		}
-	}
+    while (fgets(line, 128, fp) != NULL) {
 
-	int pos = sprintf(buf, "%lu,%u,%lu,%lu,%lu,%u",
-			st_mem.frmkb,
-			0, /* used */
-			st_mem.bufkb,
-			st_mem.camkb,
-			st_mem.tlmkb,
-			0 /* util */);
-	buf[pos] = '\0';
-	set_mod_record(mod, buf);
-	fclose(fp);
-	return;
+        if (!strncmp(line, "MemTotal:", 9)) {
+            /* Read the total amount of memory in kB */
+            sscanf(line + 9, "%lu", &st_mem.tlmkb);
+        }
+        else if (!strncmp(line, "MemFree:", 8)) {
+            /* Read the amount of free memory in kB */
+            sscanf(line + 8, "%lu", &st_mem.frmkb);
+        }
+        else if (!strncmp(line, "Buffers:", 8)) {
+            /* Read the amount of buffered memory in kB */
+            sscanf(line + 8, "%lu", &st_mem.bufkb);
+        }
+        else if (!strncmp(line, "Cached:", 7)) {
+            /* Read the amount of cached memory in kB */
+            sscanf(line + 7, "%lu", &st_mem.camkb);
+        }
+        else if (!strncmp(line, "Active:", 7)) {
+            /* Read the amount of Active memory in kB */
+            sscanf(line + 7, "%lu", &st_mem.acmkb);
+        }
+        else if (!strncmp(line, "Inactive:", 9)) {
+            /* Read the amount of Inactive memory in kB */
+            sscanf(line + 9, "%lu", &st_mem.iamkb);
+        }
+        else if (!strncmp(line, "Slab:", 5)) {
+            /* Read the amount of Slab memory in kB */
+            sscanf(line + 5, "%lu", &st_mem.slmkb);
+        }
+        else if (!strncmp(line, "SwapCached:", 11)) {
+            /* Read the amount of cached swap in kB */
+            sscanf(line + 11, "%lu", &st_mem.caskb);
+        }
+        else if (!strncmp(line, "SwapTotal:", 10)) {
+            /* Read the total amount of swap memory in kB */
+            sscanf(line + 10, "%lu", &st_mem.tlskb);
+        }
+        else if (!strncmp(line, "SwapFree:", 9)) {
+            /* Read the amount of free swap memory in kB */
+            sscanf(line + 9, "%lu", &st_mem.frskb);
+        }
+        else if (!strncmp(line, "Committed_AS:", 13)) {
+            /* Read the amount of commited memory in kB */
+            sscanf(line + 13, "%lu", &st_mem.comkb);
+        }
+    }
+
+    int pos = sprintf(buf, "%lu,%u,%lu,%lu,%lu,%u",
+            st_mem.frmkb,
+            0, /* used */
+            st_mem.bufkb,
+            st_mem.camkb,
+            st_mem.tlmkb,
+            0 /* util */);
+    buf[pos] = '\0';
+    set_mod_record(mod, buf);
+    fclose(fp);
+    return;
 }
-static void set_mem_record(struct module *mod, double st_array[],
-		U_64 pre_array[], U_64 cur_array[], int inter)
+static void
+set_mem_record(struct module *mod, double st_array[],
+    U_64 pre_array[], U_64 cur_array[], int inter)
 {
-	st_array[0] = cur_array[0]<<10;
-	st_array[1] = (cur_array[4] - cur_array[0] -cur_array[2] -cur_array[3])<<10;
-	st_array[2] = cur_array[2]<<10;
-	st_array[3] = cur_array[3]<<10;
-	st_array[4] = cur_array[4]<<10;
-	st_array[5] = st_array[1] * 100.0 / (cur_array[4]<<10);
+    int i;
+    if ((cur_array[4] - cur_array[0] -cur_array[2] -cur_array[3]) < 0) {
+        for (i = 0; i < 6; i++) 
+            st_array[i] = -1;
+        return;
+    }
+    st_array[0] = cur_array[0]<<10;
+    st_array[1] = (cur_array[4] - cur_array[0] -cur_array[2] -cur_array[3])<<10;
+    st_array[2] = cur_array[2]<<10;
+    st_array[3] = cur_array[3]<<10;
+    st_array[4] = cur_array[4]<<10;
+    st_array[5] = st_array[1] * 100.0 / (cur_array[4]<<10);
 }
 
 static struct mod_info mem_info[] = {
-	{"  free", DETAIL_BIT,  0,  STATS_NULL},
-	{"  used", DETAIL_BIT,  0,  STATS_NULL},
-	{"  buff", DETAIL_BIT, 0,  STATS_NULL},
-	{"  cach", DETAIL_BIT,  0,  STATS_NULL},
-	{" total", DETAIL_BIT,  0,  STATS_NULL},
-	{"  util", SUMMARY_BIT,  0,  STATS_NULL}
+    {"  free", DETAIL_BIT,  0,  STATS_NULL},
+    {"  used", DETAIL_BIT,  0,  STATS_NULL},
+    {"  buff", DETAIL_BIT, 0,  STATS_NULL},
+    {"  cach", DETAIL_BIT,  0,  STATS_NULL},
+    {" total", DETAIL_BIT,  0,  STATS_NULL},
+    {"  util", SUMMARY_BIT,  0,  STATS_NULL}
 };
 
-void mod_register(struct module *mod)
+void
+mod_register(struct module *mod)
 {
-	register_mod_fileds(mod, "--mem", mem_usage, mem_info, 6, read_mem_stats, set_mem_record);
+    register_mod_fields(mod, "--mem", mem_usage, mem_info, 6, read_mem_stats, set_mem_record);
 }
diff --git a/modules/mod_ncpu.c b/modules/mod_ncpu.c
index ecf4e06..10dfa1d 100644
--- a/modules/mod_ncpu.c
+++ b/modules/mod_ncpu.c
@@ -4,15 +4,15 @@
  * Structure for CPU infomation.
  */
 struct stats_cpu {
-	unsigned long long cpu_user;
-	unsigned long long cpu_nice;
-	unsigned long long cpu_sys;
-	unsigned long long cpu_idle;
-	unsigned long long cpu_iowait;
-	unsigned long long cpu_steal;
-	unsigned long long cpu_hardirq;
-	unsigned long long cpu_softirq;
-	unsigned long long cpu_guest;
+    unsigned long long cpu_user;
+    unsigned long long cpu_nice;
+    unsigned long long cpu_sys;
+    unsigned long long cpu_idle;
+    unsigned long long cpu_iowait;
+    unsigned long long cpu_steal;
+    unsigned long long cpu_hardirq;
+    unsigned long long cpu_softirq;
+    unsigned long long cpu_guest;
 };
 
 #define STATS_CPU_SIZE (sizeof(struct stats_cpu))
@@ -20,98 +20,100 @@ struct stats_cpu {
 static char *cpu_usage = "    --ncpu               CPU share (user, system, interrupt, nice, & idle)";
 
 
-static void read_cpu_stats(struct module *mod)
+static void
+read_cpu_stats(struct module *mod)
 {
-	FILE *fp;
-	int pos = 0;
-	char line[LEN_4096];
-	char buf[LEN_4096];
-	char cpuname[16];
-	memset(buf, 0, LEN_4096);
-	struct stats_cpu st_cpu;
-	memset(&st_cpu, 0, sizeof(struct stats_cpu));
-	//unsigned long long cpu_util;
-	if ((fp = fopen(STAT, "r")) == NULL) {
-		return;
-	}
-	while (fgets(line, LEN_4096, fp) != NULL) {
-		if (!strncmp(line, "cpu", 3)) {
-			/*
-			 * Read the number of jiffies spent in the different modes
-			 * (user, nice, etc.) among all proc. CPU usage is not reduced
-			 * to one processor to avoid rounding problems.
-			 */
-			sscanf(line,"%4s",cpuname);
-			if(strcmp(cpuname,"cpu") == 0)
-				continue;
-			sscanf(line+5, "%llu %llu %llu %llu %llu %llu %llu %llu %llu",
-					&st_cpu.cpu_user,
-					&st_cpu.cpu_nice,
-					&st_cpu.cpu_sys,
-					&st_cpu.cpu_idle,
-					&st_cpu.cpu_iowait,
-					&st_cpu.cpu_hardirq,
-					&st_cpu.cpu_softirq,
-					&st_cpu.cpu_steal,
-					&st_cpu.cpu_guest);
+    int               pos = 0;
+    char              line[LEN_1M];
+    char              buf[LEN_1M];
+    char              cpuname[16];
+    FILE             *fp;
+    struct stats_cpu  st_cpu;
 
-			pos += sprintf(buf + pos, "%s=%llu,%llu,%llu,%llu,%llu,%llu,%llu,%llu,%llu",
-					/* the store order is not same as read procedure */
-					cpuname,
-					st_cpu.cpu_user,
-					st_cpu.cpu_sys,
-					st_cpu.cpu_iowait,
-					st_cpu.cpu_hardirq,
-					st_cpu.cpu_softirq,
-					st_cpu.cpu_idle,
-					st_cpu.cpu_nice,
-					st_cpu.cpu_steal,
-					st_cpu.cpu_guest);
-			pos += sprintf(buf + pos, ITEM_SPLIT);
-		}
-	}
-	if(pos) {
-		buf[pos] = '\0';
-		set_mod_record(mod, buf);
-	}
-	fclose(fp);
-	return;
+    memset(buf, 0, LEN_1M);
+    memset(&st_cpu, 0, sizeof(struct stats_cpu));
+    if ((fp = fopen(STAT, "r")) == NULL) {
+        return;
+    }
+    while (fgets(line, LEN_1M, fp) != NULL) {
+        if (!strncmp(line, "cpu", 3)) {
+            /*
+             * Read the number of jiffies spent in the different modes
+             * (user, nice, etc.) among all proc. CPU usage is not reduced
+             * to one processor to avoid rounding problems.
+             */
+            sscanf(line, "%s", cpuname);
+            if(strcmp(cpuname, "cpu") == 0)
+                continue;
+            sscanf(line + strlen(cpuname), "%llu %llu %llu %llu %llu %llu %llu %llu %llu",
+                    &st_cpu.cpu_user,
+                    &st_cpu.cpu_nice,
+                    &st_cpu.cpu_sys,
+                    &st_cpu.cpu_idle,
+                    &st_cpu.cpu_iowait,
+                    &st_cpu.cpu_hardirq,
+                    &st_cpu.cpu_softirq,
+                    &st_cpu.cpu_steal,
+                    &st_cpu.cpu_guest);
+
+            pos += snprintf(buf + pos, LEN_1M - pos, "%s=%llu,%llu,%llu,%llu,%llu,%llu,%llu,%llu,%llu" ITEM_SPLIT,
+                    /* the store order is not same as read procedure */
+                    cpuname,
+                    st_cpu.cpu_user,
+                    st_cpu.cpu_sys,
+                    st_cpu.cpu_iowait,
+                    st_cpu.cpu_hardirq,
+                    st_cpu.cpu_softirq,
+                    st_cpu.cpu_idle,
+                    st_cpu.cpu_nice,
+                    st_cpu.cpu_steal,
+		    st_cpu.cpu_guest);
+	    if (strlen(buf) == LEN_1M - 1) {
+                fclose(fp);
+                return;
+	    }
+        }
+    }
+    set_mod_record(mod, buf);
+    fclose(fp);
+    return;
 }
 
-static void set_cpu_record(struct module *mod, double st_array[],
-		U_64 pre_array[], U_64 cur_array[], int inter)
+static void
+set_cpu_record(struct module *mod, double st_array[],
+    U_64 pre_array[], U_64 cur_array[], int inter)
 {
-	U_64 pre_total, cur_total;
-	int i;
-	pre_total = cur_total = 0;
+    int    i;
+    U_64   pre_total, cur_total;
+    pre_total = cur_total = 0;
 
-	for (i = 0; i < mod->n_col; i++) {
-		pre_total += pre_array[i];
-		cur_total += cur_array[i];
-	}
-	/* set st record */
-	for (i = 0; i <= 4; i++) {
-		if(cur_array[i] >= pre_array[i])
-			st_array[i] = (cur_array[i] - pre_array[i]) * 100.0 / (cur_total - pre_total);
-	}
-	if(cur_array[5] >= pre_array[5])
-		st_array[5] = 100.0 - (cur_array[5] - pre_array[5]) * 100.0 / (cur_total - pre_total);
+    for (i = 0; i < mod->n_col; i++) {
+        pre_total += pre_array[i];
+        cur_total += cur_array[i];
+    }
+    /* set st record */
+    for (i = 0; i <= 4; i++) {
+        if(cur_array[i] >= pre_array[i])
+            st_array[i] = (cur_array[i] - pre_array[i]) * 100.0 / (cur_total - pre_total);
+    }
+    if(cur_array[5] >= pre_array[5])
+        st_array[5] = 100.0 - (cur_array[5] - pre_array[5]) * 100.0 / (cur_total - pre_total);
 }
 
-
 static struct mod_info cpu_info[] = {
-	{"  user", DETAIL_BIT,  0,  STATS_NULL},
-	{"   sys", DETAIL_BIT,  0,  STATS_NULL},
-	{"  wait", DETAIL_BIT,  0,  STATS_NULL},
-	{"  hirq", DETAIL_BIT,  0,  STATS_NULL},
-	{"  sirq", DETAIL_BIT,  0,  STATS_NULL},
-	{"  util", SUMMARY_BIT,  0,  STATS_NULL},
-	{"  nice", HIDE_BIT,  0,  STATS_NULL},
-	{" steal", HIDE_BIT,  0,  STATS_NULL},
-	{" guest", HIDE_BIT,  0,  STATS_NULL},
+    {"  user", DETAIL_BIT,  0,  STATS_NULL},
+    {"   sys", DETAIL_BIT,  0,  STATS_NULL},
+    {"  wait", DETAIL_BIT,  0,  STATS_NULL},
+    {"  hirq", DETAIL_BIT,  0,  STATS_NULL},
+    {"  sirq", DETAIL_BIT,  0,  STATS_NULL},
+    {"  util", SUMMARY_BIT,  0,  STATS_NULL},
+    {"  nice", HIDE_BIT,  0,  STATS_NULL},
+    {" steal", HIDE_BIT,  0,  STATS_NULL},
+    {" guest", HIDE_BIT,  0,  STATS_NULL},
 };
 
-void mod_register(struct module *mod)
+void
+mod_register(struct module *mod)
 {
-	register_mod_fileds(mod, "--ncpu", cpu_usage, cpu_info, 9, read_cpu_stats, set_cpu_record);
+    register_mod_fields(mod, "--ncpu", cpu_usage, cpu_info, 9, read_cpu_stats, set_cpu_record);
 }
diff --git a/modules/mod_nginx.c b/modules/mod_nginx.c
index 7d70894..0d375e1 100644
--- a/modules/mod_nginx.c
+++ b/modules/mod_nginx.c
@@ -1,189 +1,290 @@
-#include <sys/socket.h>
-#include <sys/un.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#include <fcntl.h>
-#include "tsar.h"
-
-struct stats_nginx {
-	unsigned long long naccept;     /* accepted connections */
-	unsigned long long nhandled;    /* handled connections */
-	unsigned long long nrequest;    /* handled requests */
-	unsigned long long nactive;     /* number of all open connections including connections to backends */
-	unsigned long long nreading;    /* nginx reads request header */
-	unsigned long long nwriting;    /* nginx reads request body, processes request, or writes response to a client */
-	unsigned long long nwaiting;    /* keep-alive connections, actually it is active - (reading + writing) */
-	unsigned long long nrstime;     /* reponse time of handled requests */
-};
-
-struct hostinfo {
-	char *host;
-	int port;
-	char *server_name;
-	char *uri;
-};
-
-static char *nginx_usage = "    --nginx            nginx statistics";
-
-static struct mod_info nginx_info[] = {
-	{"accept", DETAIL_BIT,  0,  STATS_SUB},
-	{"handle", DETAIL_BIT,  0,  STATS_SUB},
-	{"  reqs", DETAIL_BIT,  0,  STATS_SUB},
-	{"active", DETAIL_BIT,  0,  STATS_NULL},
-	{"  read", DETAIL_BIT,  0,  STATS_NULL},
-	{" write", DETAIL_BIT,  0,  STATS_NULL},
-	{"  wait", DETAIL_BIT,  0,  STATS_NULL},
-	{"   qps", SUMMARY_BIT, 0,  STATS_SUB_INTER},
-	{"    rt", SUMMARY_BIT, 0,  STATS_NULL},
-};
-
-
-static void set_nginx_record(struct module *mod, double st_array[],
-		U_64 pre_array[], U_64 cur_array[], int inter)
-{
-	int i;
-	for (i = 0; i < 3; i++) {
-		if (cur_array[i] >= pre_array[i]) {
-			st_array[i] = cur_array[i] - pre_array[i];
-		}
-	}
-
-	for (i = 3; i < 7; i++) {
-		st_array[i] = cur_array[i];
-	}
-
-	if (cur_array[2] >= pre_array[2]) {
-		st_array[7] = (cur_array[2] - pre_array[2]) * 1.0 / inter;
-	}
-
-	if (cur_array[8] >= pre_array[8]) {
-		if (cur_array[2] > pre_array[2]) {
-			st_array[8] = (cur_array[8] - pre_array[8]) * 1.0 / (cur_array[2] - pre_array[2]);
-		}
-	}
-}
-
-
-static void init_nginx_host_info(struct hostinfo *p)
-{
-	char *port;
-
-	p->host = getenv("NGX_TSAR_HOST");
-	p->host = p->host ? p->host : "127.0.0.1";
-
-	port = getenv("NGX_TSAR_PORT");
-	p->port = port ? atoi(port) : 80;
-
-	p->uri = getenv("NGX_TSAR_URI");
-	p->uri = p->uri ? p->uri : "/nginx_status";
-
-	p->server_name = getenv("NGX_TSAR_SERVER_NAME");
-	p->server_name = p->server_name ? p->server_name : "status.taobao.com";
-}
-
-
-void read_nginx_stats(struct module *mod)
-{
-	int write_flag = 0, addr_len, domain;
-	int m, sockfd, send, pos;
-	void *addr;
-	char buf[LEN_4096], request[LEN_4096], line[LEN_4096];
-
-	struct sockaddr_in servaddr;
-	struct sockaddr_un servaddr_un;
-	FILE *stream = NULL;
-	struct hostinfo hinfo;
-	init_nginx_host_info(&hinfo);
-	struct stats_nginx st_nginx;
-	memset(&st_nginx, 0, sizeof(struct stats_nginx));
-
-	if (*hinfo.host == '/') {
-		addr = &servaddr_un;
-		addr_len = sizeof(servaddr_un);
-		bzero(addr, addr_len);
-		domain = AF_LOCAL;
-		servaddr_un.sun_family = AF_LOCAL;
-		strncpy(servaddr_un.sun_path, hinfo.host, sizeof(servaddr_un.sun_path) - 1);
-
-	} else {
-		addr = &servaddr;
-		addr_len = sizeof(servaddr);
-		bzero(addr, addr_len);
-		domain = AF_INET;
-		servaddr.sin_family = AF_INET;
-		servaddr.sin_port = htons(hinfo.port);
-		inet_pton(AF_INET, hinfo.host, &servaddr.sin_addr);
-	}
-
-
-	if ((sockfd = socket(domain, SOCK_STREAM, 0)) == -1) {
-		goto writebuf;
-	}
-
-	sprintf(request,
-			"GET %s HTTP/1.0\r\n"
-			"User-Agent: taobot\r\n"
-			"Host: %s\r\n"
-			"Accept:*/*\r\n"
-			"Connection: Close\r\n\r\n",
-			hinfo.uri, hinfo.server_name);
-
-	if ((m = connect(sockfd, (struct sockaddr *) addr, addr_len)) == -1 ) {
-		goto writebuf;
-	}
-
-	if ((send = write(sockfd, request, strlen(request))) == -1) {
-		goto writebuf;
-	}
-
-	if ((stream = fdopen(sockfd, "r")) == NULL) {
-		goto writebuf;
-	}
-
-	while (fgets(line, LEN_4096, stream) != NULL) {
-		if (!strncmp(line, "Active connections:", sizeof("Active connections:") - 1)) {
-			sscanf(line + sizeof("Active connections:"), "%llu", &st_nginx.nactive);
-		} else if (!strncmp(line, " ", 1)) {
-			sscanf(line + 1, "%llu %llu %llu %llu",
-					&st_nginx.naccept, &st_nginx.nhandled, &st_nginx.nrequest, &st_nginx.nrstime);
-			write_flag = 1;
-		} else if (!strncmp(line, "Reading:", sizeof("Reading:") - 1)) {
-			sscanf(line, "Reading: %llu Writing: %llu Waiting: %llu",
-					&st_nginx.nreading, &st_nginx.nwriting, &st_nginx.nwaiting);
-		}
-		else
-			;
-	}
-
-writebuf:
-	if (stream) {
-		fclose(stream);
-	}
-
-	if (sockfd != -1) {
-		close(sockfd);
-	}
-
-	if (write_flag) {
-		pos = sprintf(buf, "%lld,%lld,%lld,%lld,%lld,%lld,%lld,%lld,%lld",
-				st_nginx.naccept,
-				st_nginx.nhandled,
-				st_nginx.nrequest,
-				st_nginx.nactive,
-				st_nginx.nreading,
-				st_nginx.nwriting,
-				st_nginx.nwaiting,
-				st_nginx.nrequest,
-				st_nginx.nrstime
-			     );
-
-		buf[pos] = '\0';
-		set_mod_record(mod, buf);
-	}
-}
-
-
-void mod_register(struct module *mod)
-{
-	register_mod_fileds(mod, "--nginx", nginx_usage, nginx_info, 9, read_nginx_stats, set_nginx_record);
-}
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <fcntl.h>
+#include "tsar.h"
+
+struct stats_nginx {
+    unsigned long long naccept;     /* accepted connections */
+    unsigned long long nhandled;    /* handled connections */
+    unsigned long long nrequest;    /* handled requests */
+    unsigned long long nactive;     /* number of all open connections including connections to backends */
+    unsigned long long nreading;    /* nginx reads request header */
+    unsigned long long nwriting;    /* nginx reads request body, processes request, or writes response to a client */
+    unsigned long long nwaiting;    /* keep-alive connections, actually it is active - (reading + writing) */
+    unsigned long long nrstime;     /* reponse time of handled requests */
+    unsigned long long nspdy;       /* spdy requests */
+    unsigned long long nsslhds;     /* ssl handshake */
+    unsigned long long nssl;        /* ssl requests */
+    unsigned long long nsslk;       /* ssl keepalive requests */
+    unsigned long long nsslf;       /* ssl failed request */
+    unsigned long long nsslv3f;     /* sslv3 failed request */
+    unsigned long long nhttp2;      /* http2 requests */
+};
+
+struct hostinfo {
+    char *host;
+    int   port;
+    char *server_name;
+    char *uri;
+};
+
+static char *nginx_usage = "    --nginx             nginx statistics";
+
+static struct mod_info nginx_info[] = {
+    {"accept", DETAIL_BIT,  0,  STATS_SUB},
+    {"handle", DETAIL_BIT,  0,  STATS_SUB},
+    {"  reqs", DETAIL_BIT,  0,  STATS_SUB},
+    {"active", DETAIL_BIT,  0,  STATS_NULL},
+    {"  read", DETAIL_BIT,  0,  STATS_NULL},
+    {" write", DETAIL_BIT,  0,  STATS_NULL},
+    {"  wait", DETAIL_BIT,  0,  STATS_NULL},
+    {"   qps", SUMMARY_BIT, 0,  STATS_SUB_INTER},
+    {"    rt", SUMMARY_BIT, 0,  STATS_NULL},
+    {"sslqps", SUMMARY_BIT, 0,  STATS_SUB_INTER},
+    {"spdyps", SUMMARY_BIT, 0,  STATS_SUB_INTER},
+    {"  sslf", SUMMARY_BIT, 0,  STATS_SUB_INTER},
+    {"sslv3f", SUMMARY_BIT, 0,  STATS_SUB_INTER},
+    {" h2qps", SUMMARY_BIT, 0,  STATS_SUB_INTER},
+    {"sslhds", SUMMARY_BIT, 0,  STATS_SUB_INTER},
+    {"  sslk", SUMMARY_BIT, 0,  STATS_SUB_INTER},
+};
+
+
+static void
+set_nginx_record(struct module *mod, double st_array[],
+    U_64 pre_array[], U_64 cur_array[], int inter)
+{
+    int i;
+    for (i = 0; i < 3; i++) {
+        if (cur_array[i] >= pre_array[i]) {
+            st_array[i] = cur_array[i] - pre_array[i];
+        } else {
+            st_array[i] = 0;
+        }
+    }
+
+    for (i = 3; i < 7; i++) {
+        st_array[i] = cur_array[i];
+    }
+
+    if (cur_array[2] >= pre_array[2]) {
+        st_array[7] = (cur_array[2] - pre_array[2]) * 1.0 / inter;
+    } else {
+        st_array[7] = 0;
+    }
+
+    if (cur_array[8] >= pre_array[8]) {
+        if (cur_array[2] > pre_array[2]) {
+            st_array[8] = (cur_array[8] - pre_array[8]) * 1.0 / (cur_array[2] - pre_array[2]);
+        } else {
+            st_array[8] = 0;
+        }
+    }
+
+    for (i = 9; i < 16;  i++){
+        if (cur_array[i] >= pre_array[i]) {
+            st_array[i] = (cur_array[i] - pre_array[i]) * 1.0 / inter;
+        } else {
+            st_array[i] = 0;
+        }
+    }
+}
+
+
+static void
+init_nginx_host_info(struct hostinfo *p)
+{
+    char *port;
+
+    p->host = getenv("NGX_TSAR_HOST");
+    p->host = p->host ? p->host : "127.0.0.1";
+
+    port = getenv("NGX_TSAR_PORT");
+    p->port = port ? atoi(port) : 80;
+
+    p->uri = getenv("NGX_TSAR_URI");
+    p->uri = p->uri ? p->uri : "/nginx_status";
+
+    p->server_name = getenv("NGX_TSAR_SERVER_NAME");
+    p->server_name = p->server_name ? p->server_name : "status.taobao.com";
+}
+
+
+static void
+read_nginx_stats(struct module *mod, char *parameter)
+{
+    int                 write_flag = 0, addr_len, domain;
+    int                 m, sockfd, send, pos;
+    void               *addr;
+    char                buf[LEN_4096], request[LEN_4096], line[LEN_4096];
+    FILE               *stream = NULL;
+
+    struct timeval      timeout;
+    struct hostinfo     hinfo;
+    struct sockaddr_in  servaddr;
+    struct sockaddr_un  servaddr_un;
+
+
+    init_nginx_host_info(&hinfo);
+    if (atoi(parameter) != 0) {
+       hinfo.port = atoi(parameter);
+    }
+    struct stats_nginx st_nginx;
+    memset(&st_nginx, 0, sizeof(struct stats_nginx));
+
+    if (*hinfo.host == '/') {
+        addr = &servaddr_un;
+        addr_len = sizeof(servaddr_un);
+        bzero(addr, addr_len);
+        domain = AF_LOCAL;
+        servaddr_un.sun_family = AF_LOCAL;
+        strncpy(servaddr_un.sun_path, hinfo.host, sizeof(servaddr_un.sun_path) - 1);
+
+    } else {
+        addr = &servaddr;
+        addr_len = sizeof(servaddr);
+        bzero(addr, addr_len);
+        domain = AF_INET;
+        servaddr.sin_family = AF_INET;
+        servaddr.sin_port = htons(hinfo.port);
+        inet_pton(AF_INET, hinfo.host, &servaddr.sin_addr);
+    }
+
+    if ((sockfd = socket(domain, SOCK_STREAM, 0)) == -1) {
+        goto writebuf;
+    }
+
+    sprintf(request,
+            "GET %s HTTP/1.0\r\n"
+            "User-Agent: taobot\r\n"
+            "Host: %s\r\n"
+            "Accept:*/*\r\n"
+            "Connection: Close\r\n\r\n",
+            hinfo.uri, hinfo.server_name);
+
+    if ((m = connect(sockfd, (struct sockaddr *) addr, addr_len)) == -1 ) {
+        goto writebuf;
+    }
+
+    timeout.tv_sec = 10;
+    timeout.tv_usec = 0;
+    setsockopt(sockfd, SOL_SOCKET, SO_SNDTIMEO, (char *)&timeout, sizeof(struct timeval));
+    setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, (char *)&timeout, sizeof(struct timeval));
+
+    if ((send = write(sockfd, request, strlen(request))) == -1) {
+        goto writebuf;
+    }
+
+    if ((stream = fdopen(sockfd, "r")) == NULL) {
+        goto writebuf;
+    }
+
+    while (fgets(line, LEN_4096, stream) != NULL) {
+        if (!strncmp(line, "Active connections:", sizeof("Active connections:") - 1)) {
+            sscanf(line + sizeof("Active connections:"), "%llu", &st_nginx.nactive);
+            write_flag = 1;
+        } else if (!strncmp(line,
+                            "server accepts handled requests request_time",
+                            sizeof("server accepts handled requests request_time") - 1)
+                  ) {
+            /*for tengine*/
+            if (fgets(line, LEN_4096, stream) != NULL) {
+                 if (!strncmp(line, " ", 1)) {
+                    sscanf(line + 1, "%llu %llu %llu %llu",
+                             &st_nginx.naccept, &st_nginx.nhandled, &st_nginx.nrequest, &st_nginx.nrstime);
+                    write_flag = 1;
+                }
+            }
+        } else if (!strncmp(line,
+                            "server accepts handled requests",
+                            sizeof("server accepts handled requests") - 1)
+                  ) {
+            /*for nginx*/
+            if (fgets(line, LEN_4096, stream) != NULL) {
+                 if (!strncmp(line, " ", 1)) {
+                    sscanf(line + 1, "%llu %llu %llu",
+                             &st_nginx.naccept, &st_nginx.nhandled, &st_nginx.nrequest);
+                    write_flag = 1;
+                }
+            }
+        } else if (!strncmp(line, "Server accepts:", sizeof("Server accepts:") - 1)) {
+            sscanf(line , "Server accepts: %llu handled: %llu requests: %llu request_time: %llu",
+                    &st_nginx.naccept, &st_nginx.nhandled, &st_nginx.nrequest, &st_nginx.nrstime);
+            write_flag = 1;
+
+        } else if (!strncmp(line, "Reading:", sizeof("Reading:") - 1)) {
+            sscanf(line, "Reading: %llu Writing: %llu Waiting: %llu",
+                    &st_nginx.nreading, &st_nginx.nwriting, &st_nginx.nwaiting);
+            write_flag = 1;
+        } else if (!strncmp(line, "SSL:", sizeof("SSL:") - 1)) {
+            sscanf(line, "SSL: %llu SPDY: %llu",
+                    &st_nginx.nssl, &st_nginx.nspdy);
+            write_flag = 1;
+        } else if (!strncmp(line, "HTTP2:", sizeof("HTTP2:") - 1)) {
+            sscanf(line, "HTTP2: %llu",
+                    &st_nginx.nhttp2);
+            write_flag = 1;
+        } else if (!strncmp(line, "SSL_failed:", sizeof("SSL_failed:") - 1)) {
+            sscanf(line, "SSL_failed: %llu",
+                    &st_nginx.nsslf);
+            write_flag = 1;
+        } else if (!strncmp(line, "SSLv3_failed:", sizeof("SSLv3_failed:") - 1)) {
+            sscanf(line, "SSLv3_failed: %llu",
+                    &st_nginx.nsslv3f);
+            write_flag = 1;
+        } else if (!strncmp(line, "SSL_handshake:", sizeof("SSL_handshake:") - 1)) {
+            sscanf(line, "SSL_handshake: %llu",
+                    &st_nginx.nsslhds);
+            write_flag = 1;
+        } else if (!strncmp(line, "SSL_keepalive_reqs:", sizeof("SSL_keepalive_reqs:") - 1)) {
+            sscanf(line, "SSL_keepalive_reqs: %llu",
+                    &st_nginx.nsslk);
+            write_flag = 1;
+        } else {
+            ;
+        }
+    }
+    if (st_nginx.nrequest == 0) {
+        write_flag = 0;
+    }
+
+writebuf:
+    if (stream) {
+        fclose(stream);
+    }
+
+    if (sockfd != -1) {
+        close(sockfd);
+    }
+
+    if (write_flag) {
+        pos = sprintf(buf, "%lld,%lld,%lld,%lld,%lld,%lld,%lld,%lld,%lld,%lld,%lld,%lld,%lld,%lld,%lld,%lld",
+                st_nginx.naccept,
+                st_nginx.nhandled,
+                st_nginx.nrequest,
+                st_nginx.nactive,
+                st_nginx.nreading,
+                st_nginx.nwriting,
+                st_nginx.nwaiting,
+                st_nginx.nrequest,
+                st_nginx.nrstime,
+                st_nginx.nssl,
+                st_nginx.nspdy,
+                st_nginx.nsslf,
+                st_nginx.nsslv3f,
+                st_nginx.nhttp2,
+                st_nginx.nsslhds,
+                st_nginx.nsslk
+                 );
+        buf[pos] = '\0';
+        set_mod_record(mod, buf);
+    }
+}
+
+void
+mod_register(struct module *mod)
+{
+    register_mod_fields(mod, "--nginx", nginx_usage, nginx_info, 16, read_nginx_stats, set_nginx_record);
+}
diff --git a/modules/mod_paging.c b/modules/mod_paging.c
deleted file mode 100644
index e3065a6..0000000
--- a/modules/mod_paging.c
+++ /dev/null
@@ -1,223 +0,0 @@
-#include "public.h"
-
-#define PAGING_DETAIL_HDR(d)				\
-	"  pgin"d" pgout"d" fault"d"majflt"d		\
-"  free"d" scank"d" scand"d" steal"
-
-#define PAGING_STORE_FMT(d)			\
-	"%ld"d"%ld"d"%ld"d"%ld"d		\
-"%ld"d"%ld"d"%ld"d"%ld"
-
-#define PAGING_DETAIL_FMT(d)		\
-	"%5.1f"d"%5.1f"d"%5.1f"d"%5.1f"d	\
-"%5.1f"d"%5.1f"d"%5.1f"d"%5.1f"
-
-#define PAGING_SUMMARY_HDR(d)			\
-	"  pgin"d" pgout"
-
-char *paging_usage = "    --paging            Paging statistics";
-
-/* Structure for paging statistics */
-struct stats_paging {
-	unsigned long pgpgin;
-	unsigned long pgpgout;
-	unsigned long pgfault;
-	unsigned long pgmajfault;
-	unsigned long pgfree;
-	unsigned long pgscan_kswapd;
-	unsigned long pgscan_direct;
-	unsigned long pgsteal;
-}s_st_paging[2];
-
-#define PAGING_STRING_OPS(str, ops, fmt, stat, d)	\
-	ops(str, fmt,					\
-			stat d pgpgin,				\
-			stat d pgpgout,				\
-			stat d pgfault,				\
-			stat d pgmajfault,				\
-			stat d pgfree,				\
-			stat d pgscan_kswapd,			\
-			stat d pgscan_direct,			\
-			stat d pgsteal)
-
-#define STATS_PAGING_SIZE (sizeof(struct stats_paging))
-
-union paging_statistics {
-	struct paging_detail_statistics {
-		double in;
-		double out;
-		double fault;
-		double majfault;
-		double free;
-		double kswapd;
-		double direct;
-		double steal;
-	} paging_detail, paging_summary;
-} paging_statis[NR_ARRAY];
-
-//extern unsigned long itv, oitv;
-
-
-
-/*
- *******************************************
- *
- * Read paging statistics from /proc/vmstat.
- *
- *******************************************
- */
-void read_vmstat_paging(struct module *mod, int data_type)
-{
-	FILE *fp;
-	char line[128], buf[MAX_LINE_LEN];
-	unsigned long pgtmp;
-	int ok = FALSE;
-
-	if ((fp = fopen(VMSTAT, "r")) == NULL)
-		return;
-	myalloc(st_paging, stats_paging, STATS_PAGING_SIZE);
-	st_paging->pgsteal = 0;
-	st_paging->pgscan_kswapd = st_paging->pgscan_direct = 0;
-
-	while (fgets(line, 128, fp) != NULL) {
-
-		if (!strncmp(line, "pgpgin ", 7)) {
-			/* Read number of pages the system paged in */
-			sscanf(line + 7, "%lu", &st_paging->pgpgin);
-			ok = TRUE;
-		}
-		else if (!strncmp(line, "pgpgout ", 8)) {
-			/* Read number of pages the system paged out */
-			sscanf(line + 8, "%lu", &st_paging->pgpgout);
-		}
-		else if (!strncmp(line, "pgfault ", 8)) {
-			/* Read number of faults (major+minor) made by the system */
-			sscanf(line + 8, "%lu", &st_paging->pgfault);
-		}
-		else if (!strncmp(line, "pgmajfault ", 11)) {
-			/* Read number of faults (major only) made by the system */
-			sscanf(line + 11, "%lu", &st_paging->pgmajfault);
-		}
-		else if (!strncmp(line, "pgfree ", 7)) {
-			/* Read number of pages freed by the system */
-			sscanf(line + 7, "%lu", &st_paging->pgfree);
-		}
-		else if (!strncmp(line, "pgsteal_", 8)) {
-			/* Read number of pages stolen by the system */
-			sscanf(strchr(line, ' '), "%lu", &pgtmp);
-			st_paging->pgsteal += pgtmp;
-		}
-		else if (!strncmp(line, "pgscan_kswapd_", 14)) {
-			/* Read number of pages scanned by the kswapd daemon */
-			sscanf(strchr(line, ' '), "%lu", &pgtmp);
-			st_paging->pgscan_kswapd += pgtmp;
-		}
-		else if (!strncmp(line, "pgscan_direct_", 14)) {
-			/* Read number of pages scanned directly */
-			sscanf(strchr(line, ' '), "%lu", &pgtmp);
-			st_paging->pgscan_direct += pgtmp;
-		}
-	}
-	int pos = PAGING_STRING_OPS(buf, sprintf, 
-			PAGING_STORE_FMT(DATA_SPLIT), st_paging, ->);
-	buf[pos] = '\0';
-	mod->detail = strdup(buf);
-
-	fclose(fp);
-	return;
-}
-
-char * paging_ops(char *last_record,
-		char *curr_record,
-		time_t last_time,
-		time_t curr_time,
-		int data_type,
-		int output_type)
-{
-	char buf[MAX_STRING_LEN];
-	int pos = 0;
-	unsigned long itv;
-
-	PAGING_STRING_OPS(last_record, sscanf,
-			PAGING_STORE_FMT(DATA_SPLIT), &s_st_paging[1], .);
-	PAGING_STRING_OPS(curr_record, sscanf,
-			PAGING_STORE_FMT(DATA_SPLIT), &s_st_paging[0], .);
-
-	DECLARE_TMP_MOD_STATISTICS(paging);
-
-	if (data_type == DATA_DETAIL || data_type == DATA_SUMMARY) {
-		COMPUTE_MOD_VALUE(paging, S_VALUE, detail, pgpgin, itv, in);
-		COMPUTE_MOD_VALUE(paging, S_VALUE, detail, pgpgout, itv, out);
-		COMPUTE_MOD_VALUE(paging, S_VALUE, detail, pgfault, itv, fault);
-		COMPUTE_MOD_VALUE(paging, S_VALUE, detail, pgmajfault, itv, majfault);
-		COMPUTE_MOD_VALUE(paging, S_VALUE, detail, pgfree, itv, free);
-		COMPUTE_MOD_VALUE(paging, S_VALUE, detail, pgscan_kswapd, itv, kswapd);
-		COMPUTE_MOD_VALUE(paging, S_VALUE, detail, pgscan_direct, itv, direct);
-		COMPUTE_MOD_VALUE(paging, S_VALUE, detail, pgsteal, itv, steal);
-
-		SET_MOD_STATISTICS(paging, in, itv, detail);
-		SET_MOD_STATISTICS(paging, out, itv, detail);
-		SET_MOD_STATISTICS(paging, fault, itv, detail);
-		SET_MOD_STATISTICS(paging, majfault, itv, detail);
-		SET_MOD_STATISTICS(paging, free, itv, detail);
-		SET_MOD_STATISTICS(paging, kswapd, itv, detail);
-		SET_MOD_STATISTICS(paging, direct, itv, detail);
-		SET_MOD_STATISTICS(paging, steal, itv, detail);
-	}
-	if (data_type == DATA_DETAIL) {
-		PRINT(buf + pos, paging_tmp_s.paging_detail.in, pos, output_type);
-		PRINT(buf + pos, paging_tmp_s.paging_detail.out, pos, output_type);
-		PRINT(buf + pos, paging_tmp_s.paging_detail.fault, pos, output_type);
-		PRINT(buf + pos, paging_tmp_s.paging_detail.majfault, pos, output_type);
-		PRINT(buf + pos, paging_tmp_s.paging_detail.free, pos, output_type);
-		PRINT(buf + pos, paging_tmp_s.paging_detail.kswapd, pos, output_type);
-		PRINT(buf + pos, paging_tmp_s.paging_detail.direct, pos, output_type);
-		PRINT(buf + pos, paging_tmp_s.paging_detail.steal, pos, output_type);
-	}
-	else if (data_type == DATA_SUMMARY) {
-		PRINT(buf + pos, paging_tmp_s.paging_summary.in, pos, output_type);
-		PRINT(buf + pos, paging_tmp_s.paging_summary.out, pos, output_type);
-	}
-	buf[pos - 1] = '\0';
-	return(strdup(buf));
-}
-
-static char **get_paging_avg(int data_type, int count)
-{
-	char **statis;
-	int pos[3] = {0, 0, 0};
-	int i;
-	INIT_STRING_P(statis, 3, MAX_STRING_LEN);
-	for(i = 0; i < 3; i++) {
-		if (data_type == DATA_DETAIL) {
-			__PRINT_AVG(statis, pos, paging_statis, paging_detail.in, i, count, OUTPUT_PRINT);
-			__PRINT_AVG(statis, pos, paging_statis, paging_detail.out, i, count, OUTPUT_PRINT);
-			__PRINT_AVG(statis, pos, paging_statis, paging_detail.fault, i, count, OUTPUT_PRINT);
-			__PRINT_AVG(statis, pos, paging_statis, paging_detail.majfault, i, count, OUTPUT_PRINT);
-			__PRINT_AVG(statis, pos, paging_statis, paging_detail.free, i, count, OUTPUT_PRINT);
-			__PRINT_AVG(statis, pos, paging_statis, paging_detail.kswapd, i, count, OUTPUT_PRINT);
-			__PRINT_AVG(statis, pos, paging_statis, paging_detail.direct, i, count, OUTPUT_PRINT);
-			__PRINT_AVG(statis, pos, paging_statis, paging_detail.steal, i, count, OUTPUT_PRINT);
-		} 
-		else if(data_type == DATA_SUMMARY)  {
-			__PRINT_AVG(statis, pos, paging_statis, paging_summary.in, i, count, OUTPUT_PRINT);
-			__PRINT_AVG(statis, pos, paging_statis, paging_summary.out, i, count, OUTPUT_PRINT);
-		}
-
-	}
-	return statis;
-}
-
-
-void mod_register(struct module *mod)
-{
-	sprintf(mod->detail_hdr, PAGING_DETAIL_HDR(" "));
-	sprintf(mod->summary_hdr, PAGING_SUMMARY_HDR(" "));
-	mod->usage = paging_usage;
-	sprintf(mod->opt_line, "--paging");
-	mod->data_collect = read_vmstat_paging;
-	mod->data_operation = paging_ops;
-	mod->show_avg = get_paging_avg;
-	mod->mod_free = func_mod_free;
-}
-
diff --git a/modules/mod_partition.c b/modules/mod_partition.c
index 0d9fc28..0b75f4a 100644
--- a/modules/mod_partition.c
+++ b/modules/mod_partition.c
@@ -8,142 +8,132 @@
 char *partition_usage = "    --partition         Disk and partition usage";
 
 
-#define MAXPART 20
+#define MAXPART 32
 
 struct stats_partition {
-	int bsize;                           /* block size*/
-	unsigned long long blocks;           /* total blocks*/
-	unsigned long long bfree;            /* free for non root user*/
-	unsigned long long bavail;           /* avail for root*/
-	unsigned long long itotal;
-	unsigned long long ifree;
+    int bsize;                           /* block size*/
+    unsigned long long blocks;           /* total blocks*/
+    unsigned long long bfree;            /* free for non root user*/
+    unsigned long long bavail;           /* avail for root*/
+    unsigned long long itotal;
+    unsigned long long ifree;
 };
 #define STATS_PARTITION_SIZE (sizeof(struct stats_partition))
 
-/* static int count_partition_nr(char *record) */
-/* { */
-/*         FILE *mntfile; */
-/*         struct mntent *mnt; */
-/*         int n = 0; */
-/* 	char *tmpstr; */
-/* 	tmpstr = record; */
-/* 	if (record != NULL && *record != '\0') { */
-/* 		while((tmpstr = strstr(tmpstr, ITEM_SPSTART)) != NULL) */
-/* 			tmpstr++; */
-/* 		n++; */
-/* 	} */
-/* 	else { */
-/* 		mntfile = setmntent("/etc/mtab", "r"); */
-/* 		while((mnt = getmntent(mntfile)) != NULL) { */
-/* 			if(! strncmp(mnt->mnt_fsname, "/", 1)) */
-/* 				n++; */
-/* 		}  */
-/* 	} */
-/* 	if(n > MAXPART) */
-/* 		return MAXPART; */
-/* 	else */
-/* 		return n; */
-/* } */
-
-
-int __read_partition_stat(char *fsname, struct stats_partition *sp)
+int
+__read_partition_stat(char *fsname, struct stats_partition *sp)
 {
-	struct statfs fsbuf;
-	if (!statfs(fsname, &fsbuf)) {
-		sp->bsize = fsbuf.f_bsize;
-		sp->blocks = fsbuf.f_blocks;
-		sp->bfree = fsbuf.f_bfree;
-		sp->bavail = fsbuf.f_bavail;
-		sp->itotal = fsbuf.f_files;
-		sp->ifree = fsbuf.f_ffree;
-	}
-	return 0;
+    struct statfs fsbuf;
+    if (!statfs(fsname, &fsbuf)) {
+        sp->bsize = fsbuf.f_bsize;
+        sp->blocks = fsbuf.f_blocks;
+        sp->bfree = fsbuf.f_bfree;
+        sp->bavail = fsbuf.f_bavail;
+        sp->itotal = fsbuf.f_files;
+        sp->ifree = fsbuf.f_ffree;
+    }
+    return 0;
 }
 
-int store_single_partition(char *buf, char *mntpath,
-		struct stats_partition *sp) 
+int
+store_single_partition(char *buf, char *mntpath, struct stats_partition *sp, int size)
 {
-	int len = 0;
-	float util;
-	unsigned long long nonroot_total = sp->blocks -  sp->bfree + sp->bavail;
-	if (nonroot_total != 0)
-		util = ((sp->blocks - sp->bfree) * 100) / (float)nonroot_total +
-			((sp->blocks - sp->bfree) * 100) % nonroot_total != 0;
-	else
-		util = 0;
-	len += sprintf(buf, "%s=", mntpath);
-	len += sprintf(buf+len, "%d,%lld,%lld,%lld", 
-			sp->bsize,
-			sp->bfree,
-			sp->blocks,		       
-			sp->bavail);
-	return len;
-
+    int                 len = 0;
+    int                 k = 1;
+    if (sp->bsize % 1024 != 0) {
+	    return len;
+    } else {
+	    k = sp->bsize / 1024;
+    }
+    len += snprintf(buf + len, size, "%s=%d,%lld,%lld,%lld,%lld,%lld" ITEM_SPLIT,
+            mntpath,
+            sp->bsize / k,
+            sp->bfree * k,
+            sp->blocks * k,
+            sp->bavail * k,
+            sp->ifree,
+            sp->itotal);
+    return len;
 }
 
 
-void read_partition_stat(struct module *mod)
+void
+read_partition_stat(struct module *mod)
 {
-	int part_nr, pos = 0;
-	char buf[LEN_4096];
-	memset(buf, 0, LEN_4096);
-	FILE *mntfile;
-	struct mntent *mnt = NULL;
-	struct stats_partition temp;
-
-	memset(&temp, 0, sizeof(temp));
-
-	/* part_nr = count_partition_nr(NULL); */
-
-	mntfile = setmntent("/etc/mtab", "r");
-
-	/* init part_nr */
-	part_nr = 0;
-	/* traverse the mount table */
-	while((mnt = getmntent(mntfile)) != NULL) {
-		/* only recore block filesystems */
-		if(! strncmp(mnt->mnt_fsname, "/", 1)) {
-			/* we only read MAXPART partition */
-			if(part_nr >= MAXPART) break;
-			/* read each partition infomation */
-			__read_partition_stat(mnt->mnt_dir, &temp);
-
-			/* print log to the buffer */
-			pos += store_single_partition(buf + pos, mnt->mnt_dir, &temp);
-			pos += sprintf(buf + pos, ITEM_SPLIT);
-			/* successful read */
-			part_nr++;
-			/* move the pointer to the next structure */
-		}
-	}
-	endmntent(mntfile);
-	buf[pos] = '\0';
-	set_mod_record(mod, buf);
-	return;
+    int                     part_nr, pos = 0;
+    char                    buf[LEN_1M];
+    FILE                   *mntfile;
+    struct mntent          *mnt = NULL;
+    struct stats_partition  temp;
+
+    memset(buf, 0, LEN_1M);
+    memset(&temp, 0, sizeof(temp));
+
+    /* part_nr = count_partition_nr(NULL); */
+
+    mntfile = setmntent("/etc/mtab", "r");
+
+    /* init part_nr */
+    part_nr = 0;
+    /* traverse the mount table */
+    while ((mnt = getmntent(mntfile)) != NULL) {
+        /* only recore block filesystems */
+        if (! strncmp(mnt->mnt_fsname, "/", 1)) {
+            /* we only read MAXPART partition */
+            if (part_nr >= MAXPART) break;
+            /* read each partition infomation */
+            __read_partition_stat(mnt->mnt_dir, &temp);
+
+            /* print log to the buffer */
+	    pos += store_single_partition(buf + pos, mnt->mnt_dir, &temp, LEN_1M - pos);
+            if (strlen(buf) == LEN_1M - 1) {
+                return;
+            }
+            /* successful read */
+            part_nr++;
+            /* move the pointer to the next structure */
+        }
+    }
+    endmntent(mntfile);
+    set_mod_record(mod, buf);
+    return;
 }
 
-static void set_part_record(struct module *mod, double st_array[],
-		U_64 pre_array[], U_64 cur_array[], int inter)
+static void
+set_part_record(struct module *mod, double st_array[], U_64 pre_array[], U_64 cur_array[], int inter)
 {
-	st_array[0] = cur_array[3] * cur_array[0];
-	st_array[1] = (cur_array[2] - cur_array[1]) * cur_array[0];
-	st_array[2] = cur_array[2] * cur_array[0];
-
-	U_64 used = cur_array[2] - cur_array[1];
-	U_64 nonroot_total = cur_array[2] - cur_array[1] + cur_array[3];
-
-	if(nonroot_total != 0)
-		st_array[3]= (used * 100.0) / nonroot_total + ((used * 100) % nonroot_total != 0);
+    st_array[0] = cur_array[3] * cur_array[0];
+    st_array[1] = (cur_array[2] - cur_array[1]) * cur_array[0];
+    st_array[2] = cur_array[2] * cur_array[0];
+
+    U_64 used = cur_array[2] - cur_array[1];
+    U_64 nonroot_total = cur_array[2] - cur_array[1] + cur_array[3];
+
+    if(nonroot_total != 0) {
+        st_array[3]= (used * 100.0) / nonroot_total + ((used * 100) % nonroot_total != 0);
+    }
+    if (st_array[3] > 100) {
+        st_array[3] = 100;
+    }
+    st_array[4] = cur_array[4];
+    st_array[5] = cur_array[5];
+    if (cur_array[5] >= cur_array[4] && cur_array[5] != 0) {
+        st_array[6] = (cur_array[5] - cur_array[4]) * 100.0 / cur_array[5];
+    }
 }
 
 static struct mod_info part_info[] = {
-	{" bfree", DETAIL_BIT,  MERGE_SUM,  STATS_NULL},
-	{" bused", DETAIL_BIT,  MERGE_SUM,  STATS_NULL},
-	{" btotl", DETAIL_BIT,  MERGE_SUM,  STATS_NULL},
-	{"  util", DETAIL_BIT, MERGE_AVG,  STATS_NULL},
+    {" bfree", DETAIL_BIT,  MERGE_AVG,  STATS_NULL},
+    {" bused", DETAIL_BIT,  MERGE_SUM,  STATS_NULL},
+    {" btotl", DETAIL_BIT,  MERGE_SUM,  STATS_NULL},
+    {"  util", DETAIL_BIT, MERGE_SUM,  STATS_NULL},
+    {" ifree", DETAIL_BIT, MERGE_SUM,  STATS_NULL},
+    {" itotl", DETAIL_BIT, MERGE_SUM,  STATS_NULL},
+    {" iutil", DETAIL_BIT, MERGE_SUM,  STATS_NULL},
 };
 
-void mod_register(struct module *mod)
+void
+mod_register(struct module *mod)
 {
-	register_mod_fileds(mod, "--partition", partition_usage, part_info, 4, read_partition_stat, set_part_record);
+    register_mod_fields(mod, "--partition", partition_usage, part_info, 7, read_partition_stat, set_part_record);
 }
diff --git a/modules/mod_pcsw.c b/modules/mod_pcsw.c
index 7baea1b..413c936 100644
--- a/modules/mod_pcsw.c
+++ b/modules/mod_pcsw.c
@@ -4,8 +4,8 @@
 char *pcsw_usage = "    --pcsw              Process (task) creation and context switch";
 
 struct stats_pcsw {
-	unsigned long long context_switch;
-	unsigned long processes;
+    unsigned long long context_switch;
+    unsigned long processes;
 };
 
 #define STATS_PCSW_SIZE sizeof(struct pcsw_stats)
@@ -20,44 +20,48 @@ enum {PROC, CSWCH};
  *
  ***************************************************************************
  */
-void read_stat_pcsw(struct module *mod)
+void
+read_stat_pcsw(struct module *mod)
 {
-	FILE *fp;
-	char line[LEN_4096];
-	char buf[LEN_4096];
-	memset(buf, 0, LEN_4096);
-	struct stats_pcsw st_pcsw;
-	memset(&st_pcsw, 0, sizeof(struct stats_pcsw));
-
-	if ((fp = fopen(STAT, "r")) == NULL) {
-		return;
-	}
-	while (fgets(line, LEN_4096, fp) != NULL) {
-
-		if (!strncmp(line, "ctxt ", 5)) {
-			/* Read number of context switches */
-			sscanf(line + 5, "%llu", &st_pcsw.context_switch);
-		}
-
-		else if (!strncmp(line, "processes ", 10)) {
-			/* Read number of processes created since system boot */
-			sscanf(line + 10, "%lu", &st_pcsw.processes);
-		}
-	}
-	int pos = sprintf(buf, "%lld,%ld", 
-			st_pcsw.context_switch,
-			st_pcsw.processes);
-	buf[pos] = '\0';
-	set_mod_record(mod, buf);
-	fclose(fp);
+    FILE              *fp;
+    char               line[LEN_4096];
+    char               buf[LEN_4096];
+    struct stats_pcsw  st_pcsw;
+
+    memset(buf, 0, LEN_4096);
+    memset(&st_pcsw, 0, sizeof(struct stats_pcsw));
+
+    if ((fp = fopen(STAT, "r")) == NULL) {
+        return;
+    }
+    while (fgets(line, LEN_4096, fp) != NULL) {
+
+        if (!strncmp(line, "ctxt ", 5)) {
+            /* Read number of context switches */
+            sscanf(line + 5, "%llu", &st_pcsw.context_switch);
+        }
+
+        else if (!strncmp(line, "processes ", 10)) {
+            /* Read number of processes created since system boot */
+            sscanf(line + 10, "%lu", &st_pcsw.processes);
+        }
+    }
+    int pos = sprintf(buf, "%lld,%ld",
+            st_pcsw.context_switch,
+            st_pcsw.processes);
+    buf[pos] = '\0';
+    set_mod_record(mod, buf);
+    fclose(fp);
 }
+
 static struct mod_info pcsw_info[] = {
-	{" cswch", DETAIL_BIT,  0,  STATS_SUB_INTER},
-	{"  proc", DETAIL_BIT,  0,  STATS_SUB_INTER}
+    {" cswch", DETAIL_BIT,  0,  STATS_SUB_INTER},
+    {"  proc", DETAIL_BIT,  0,  STATS_SUB_INTER}
 };
 
-void mod_register(struct module *mod)
+void
+mod_register(struct module *mod)
 {
-	register_mod_fileds(mod, "--pcsw", pcsw_usage, pcsw_info, 2, read_stat_pcsw, NULL);
+    register_mod_fields(mod, "--pcsw", pcsw_usage, pcsw_info, 2, read_stat_pcsw, NULL);
 }
 
diff --git a/modules/mod_percpu.c b/modules/mod_percpu.c
index 785e3a7..9cb3256 100644
--- a/modules/mod_percpu.c
+++ b/modules/mod_percpu.c
@@ -1,131 +1,129 @@
 #include "tsar.h"
 
 #define STAT_PATH "/proc/stat"
-#define MAX_CPUS 32
 
 static char *percpu_usage = "    --percpu            Per cpu share (user, system, interrupt, nice, & idle)";
 
 struct stats_percpu {
-	unsigned long long cpu_user;
-	unsigned long long cpu_nice;
-	unsigned long long cpu_sys;
-	unsigned long long cpu_idle;
-	unsigned long long cpu_iowait;
-	unsigned long long cpu_steal;
-	unsigned long long cpu_hardirq;
-	unsigned long long cpu_softirq;
-	unsigned long long cpu_guest;
-	char cpu_name[10];
+    unsigned long long cpu_user;
+    unsigned long long cpu_nice;
+    unsigned long long cpu_sys;
+    unsigned long long cpu_idle;
+    unsigned long long cpu_iowait;
+    unsigned long long cpu_steal;
+    unsigned long long cpu_hardirq;
+    unsigned long long cpu_softirq;
+    unsigned long long cpu_guest;
+    char cpu_name[10];
 };
 
 #define STATS_PERCPU_SIZE (sizeof(struct stats_percpu))
 
-static void read_percpu_stats(struct module *mod)
+static void
+read_percpu_stats(struct module *mod)
 {
-	FILE *fp;
-	char line[LEN_4096];
-	char buf[LEN_4096];
-	memset(buf, 0, LEN_4096);
-	struct stats_percpu st_percpu;
-	int pos = 0, cpus = 0;
+    int                  pos = 0, cpus = 0;
+    FILE                *fp;
+    char                 line[LEN_1M];
+    char                 buf[LEN_1M];
+    struct stats_percpu  st_percpu;
 
-	memset(&st_percpu, 0, STATS_PERCPU_SIZE);
-	if ((fp = fopen(STAT_PATH, "r")) == NULL) {
-		return;
-	}
-	while (fgets(line, LEN_4096, fp) != NULL) {
-		if (!strncmp(line, "cpu", 3)) {
-			/*
-			 * Read the number of jiffies spent in the different modes
-			 * (user, nice, etc.) among all proc. CPU usage is not reduced
-			 * to one processor to avoid rounding problems.
-			 */
-			sscanf(line, "%s %llu %llu %llu %llu %llu %llu %llu %llu %llu",
-					st_percpu.cpu_name,
-					&st_percpu.cpu_user,
-					&st_percpu.cpu_nice,
-					&st_percpu.cpu_sys,
-					&st_percpu.cpu_idle,
-					&st_percpu.cpu_iowait,
-					&st_percpu.cpu_hardirq,
-					&st_percpu.cpu_softirq,
-					&st_percpu.cpu_steal,
-					&st_percpu.cpu_guest);
-			if (st_percpu.cpu_name[3] == '\0') //ignore cpu summary stat
-				continue;
+    memset(buf, 0, LEN_1M);
+    memset(&st_percpu, 0, STATS_PERCPU_SIZE);
+    if ((fp = fopen(STAT_PATH, "r")) == NULL) {
+        return;
+    }
+    while (fgets(line, LEN_1M, fp) != NULL) {
+        if (!strncmp(line, "cpu", 3)) {
+            /*
+             * Read the number of jiffies spent in the different modes
+             * (user, nice, etc.) among all proc. CPU usage is not reduced
+             * to one processor to avoid rounding problems.
+             */
+            sscanf(line, "%s %llu %llu %llu %llu %llu %llu %llu %llu %llu",
+                    st_percpu.cpu_name,
+                    &st_percpu.cpu_user,
+                    &st_percpu.cpu_nice,
+                    &st_percpu.cpu_sys,
+                    &st_percpu.cpu_idle,
+                    &st_percpu.cpu_iowait,
+                    &st_percpu.cpu_hardirq,
+                    &st_percpu.cpu_softirq,
+                    &st_percpu.cpu_steal,
+                    &st_percpu.cpu_guest);
+            if (st_percpu.cpu_name[3] == '\0') //ignore cpu summary stat
+                continue;
 
-			pos += sprintf(buf + pos, "%s=%llu,%llu,%llu,%llu,%llu,%llu,%llu,%llu,%llu",
-					/* the store order is not same as read procedure */
-					st_percpu.cpu_name,
-					st_percpu.cpu_user,
-					st_percpu.cpu_sys,
-					st_percpu.cpu_iowait,
-					st_percpu.cpu_hardirq,
-					st_percpu.cpu_softirq,
-					st_percpu.cpu_idle,
-					st_percpu.cpu_nice,
-					st_percpu.cpu_steal,
-					st_percpu.cpu_guest);
-
-			pos += sprintf(buf + pos, ITEM_SPLIT);
-
-			cpus ++;
-			if (cpus > MAX_CPUS)
-				break;
-		}
-	}
-	if(pos) {
-		buf[pos] = '\0';
-		set_mod_record(mod, buf);
-	}
-	fclose(fp);
-	return;
+            pos += snprintf(buf + pos, LEN_1M - pos, "%s=%llu,%llu,%llu,%llu,%llu,%llu,%llu,%llu,%llu" ITEM_SPLIT,
+                    /* the store order is not same as read procedure */
+                    st_percpu.cpu_name,
+                    st_percpu.cpu_user,
+                    st_percpu.cpu_sys,
+                    st_percpu.cpu_iowait,
+                    st_percpu.cpu_hardirq,
+                    st_percpu.cpu_softirq,
+                    st_percpu.cpu_idle,
+                    st_percpu.cpu_nice,
+                    st_percpu.cpu_steal,
+                    st_percpu.cpu_guest);
+            if (strlen(buf) == LEN_1M - 1) {
+                fclose(fp);
+                return;
+            }
+            cpus++;
+        }
+    }
+    set_mod_record(mod, buf);
+    fclose(fp);
+    return;
 }
 
-static void set_percpu_record(struct module *mod, double st_array[],
-		U_64 pre_array[], U_64 cur_array[], int inter)
+static void
+set_percpu_record(struct module *mod, double st_array[],
+    U_64 pre_array[], U_64 cur_array[], int inter)
 {
-	U_64 pre_total, cur_total;
-	int i,j;
-	pre_total = cur_total = 0;
+    int    i, j;
+    U_64   pre_total, cur_total;
+    pre_total = cur_total = 0;
 
-	for (i = 0; i < mod->n_col; i++) {
-		if(cur_array[i] < pre_array[i]){
-			for(j = 0; j < 9; j++)
-				st_array[j] = -1;
-			return;
-		}
-		pre_total += pre_array[i];
-		cur_total += cur_array[i];
-	}
+    for (i = 0; i < mod->n_col; i++) {
+        if(cur_array[i] < pre_array[i]){
+            for(j = 0; j < 9; j++)
+                st_array[j] = -1;
+            return;
+        }
+        pre_total += pre_array[i];
+        cur_total += cur_array[i];
+    }
 
-	/* no tick changes, or tick overflows */
-	if (cur_total <= pre_total)
-		return;
-	/* set st record */
-	for (i = 0; i < 9; i++) {
-		/* st_array[5] is util, calculate it late */
-		if((i != 5) && (cur_array[i] >= pre_array[i]))
-			st_array[i] = (cur_array[i] - pre_array[i]) * 100.0 / (cur_total - pre_total);
-	}
+    /* no tick changes, or tick overflows */
+    if (cur_total <= pre_total)
+        return;
+    /* set st record */
+    for (i = 0; i < 9; i++) {
+        /* st_array[5] is util, calculate it late */
+        if((i != 5) && (cur_array[i] >= pre_array[i]))
+            st_array[i] = (cur_array[i] - pre_array[i]) * 100.0 / (cur_total - pre_total);
+    }
 
-	/* util = user + sys + hirq + sirq + nice */
-	st_array[5] = st_array[0] + st_array[1] + st_array[3] + st_array[4] + st_array[6];
+    /* util = user + sys + hirq + sirq + nice */
+    st_array[5] = st_array[0] + st_array[1] + st_array[3] + st_array[4] + st_array[6];
 }
 
 static struct mod_info percpu_info[] = {
-	{"  user", DETAIL_BIT,  0,  STATS_NULL},
-	{"   sys", DETAIL_BIT,  0,  STATS_NULL},
-	{"  wait", DETAIL_BIT,  0,  STATS_NULL},
-	{"  hirq", DETAIL_BIT,  0,  STATS_NULL},
-	{"  sirq", DETAIL_BIT,  0,  STATS_NULL},
-	{"  util", SUMMARY_BIT,  0,  STATS_NULL},
-	{"  nice", HIDE_BIT,  0,  STATS_NULL},
-	{" steal", HIDE_BIT,  0,  STATS_NULL},
-	{" guest", HIDE_BIT,  0,  STATS_NULL},
+    {"  user", DETAIL_BIT,  MERGE_SUM,  STATS_NULL},
+    {"   sys", DETAIL_BIT,  MERGE_SUM,  STATS_NULL},
+    {"  wait", DETAIL_BIT,  MERGE_SUM,  STATS_NULL},
+    {"  hirq", DETAIL_BIT,  MERGE_SUM,  STATS_NULL},
+    {"  sirq", DETAIL_BIT,  MERGE_SUM,  STATS_NULL},
+    {"  util", SUMMARY_BIT,  MERGE_SUM,  STATS_NULL},
+    {"  nice", HIDE_BIT,  MERGE_SUM,  STATS_NULL},
+    {" steal", HIDE_BIT,  MERGE_SUM,  STATS_NULL},
+    {" guest", HIDE_BIT,  MERGE_SUM,  STATS_NULL},
 };
 
-void mod_register(struct module *mod)
+void
+mod_register(struct module *mod)
 {
-	register_mod_fileds(mod, "--percpu", percpu_usage, percpu_info, 9, read_percpu_stats, set_percpu_record);
+    register_mod_fields(mod, "--percpu", percpu_usage, percpu_info, 9, read_percpu_stats, set_percpu_record);
 }
diff --git a/modules/mod_pernic.c b/modules/mod_pernic.c
new file mode 100644
index 0000000..ba6bd2e
--- /dev/null
+++ b/modules/mod_pernic.c
@@ -0,0 +1,90 @@
+#include "tsar.h"
+
+char *pernic_usage = "    --pernic            Net pernic statistics";
+
+#define MAX_NICS 8
+
+/*
+ * Structure for pernic infomation.
+ */
+struct stats_pernic {
+    unsigned long long bytein;
+    unsigned long long byteout;
+    unsigned long long pktin;
+    unsigned long long pktout;
+    char name[16];
+};
+
+#define STATS_TRAFFIC_SIZE (sizeof(struct stats_pernic))
+
+
+/*
+ * collect pernic infomation
+ */
+static void
+read_pernic_stats(struct module *mod)
+{
+    int                   pos = 0, nics = 0;
+    FILE                 *fp;
+    char                  line[LEN_1M] = {0};
+    char                  buf[LEN_1M] = {0};
+    struct stats_pernic   st_pernic;
+
+    memset(buf, 0, LEN_1M);
+    memset(&st_pernic, 0, sizeof(struct stats_pernic));
+
+    if ((fp = fopen(NET_DEV, "r")) == NULL) {
+        return;
+    }
+
+    while (fgets(line, LEN_1M, fp) != NULL) {
+        memset(&st_pernic, 0, sizeof(st_pernic));
+        if (!strstr(line, ":")) {
+            continue;
+        }
+        sscanf(line,  "%*[^a-z]%[^:]:%llu %llu %*u %*u %*u %*u %*u %*u "
+                "%llu %llu %*u %*u %*u %*u %*u %*u",
+                st_pernic.name,
+                &st_pernic.bytein,
+                &st_pernic.pktin,
+                &st_pernic.byteout,
+                &st_pernic.pktout);
+        /* if nic not used, skip it */
+        if (st_pernic.bytein == 0) {
+            continue;
+        }
+
+        pos += snprintf(buf + pos, LEN_1M - pos, "%s=%lld,%lld,%lld,%lld" ITEM_SPLIT,
+                st_pernic.name,
+                st_pernic.bytein,
+                st_pernic.byteout,
+                st_pernic.pktin,
+		st_pernic.pktout);
+        if (strlen(buf) == LEN_1M - 1) {
+            fclose(fp);
+            return;
+        }
+
+	nics++;
+        if (nics > MAX_NICS) {
+            break;
+        }
+    }
+
+    set_mod_record(mod, buf);
+    fclose(fp);
+    return;
+}
+
+static struct mod_info pernic_info[] = {
+    {" bytin", SUMMARY_BIT,  MERGE_SUM,  STATS_SUB_INTER},
+    {"bytout", SUMMARY_BIT,  MERGE_SUM,  STATS_SUB_INTER},
+    {" pktin", DETAIL_BIT,  MERGE_SUM,  STATS_SUB_INTER},
+    {"pktout", DETAIL_BIT,  MERGE_SUM,  STATS_SUB_INTER}
+};
+
+void
+mod_register(struct module *mod)
+{
+    register_mod_fields(mod, "--pernic", pernic_usage, pernic_info, 4, read_pernic_stats, NULL);
+}
diff --git a/modules/mod_proc.c b/modules/mod_proc.c
new file mode 100644
index 0000000..eaae236
--- /dev/null
+++ b/modules/mod_proc.c
@@ -0,0 +1,216 @@
+#include "tsar.h"
+
+/*
+ * Structure for Proc infomation.
+ */
+struct stats_proc {
+    unsigned long long user_cpu;
+    unsigned long long sys_cpu;
+    unsigned long long total_cpu;
+    unsigned long long mem;
+    unsigned long long total_mem;
+    unsigned long long read_bytes;
+    unsigned long long write_bytes;
+};
+
+#define PID_IO          "/proc/%u/io"
+#define PID_STAT        "/proc/%u/stat"
+#define PID_STATUS      "/proc/%u/status"
+#define STATS_PROC_SIZE (sizeof(struct stats_proc))
+
+static char *proc_usage = "    --proc              PROC info (mem cpu usage & io/fd info)";
+
+
+static void
+read_proc_stats(struct module *mod, char *parameter)
+{
+    int     nb = 0, pid[16];
+    char    buf[LEN_4096];
+    char    filename[128], line[256];
+    FILE   *fp;
+    struct  stats_proc st_proc;
+
+    memset(&st_proc, 0, sizeof(struct stats_proc));
+
+    /* get pid by proc name */
+    if (strlen(parameter) > 20) {
+        return;
+    }
+    char cmd[32] = "pidof ";
+    strncat(cmd, parameter, sizeof(cmd) - strlen(cmd) -1);
+    char  spid[256];
+    fp = popen(cmd, "r");
+    if (fp == NULL) {
+        return;
+    }
+    if(fscanf(fp, "%s", spid) == EOF) {
+        pclose(fp);
+        return;
+    }
+    pclose(fp);
+    /* split pidof into array pid */
+    char *p;
+    p = strtok(spid, " ");
+    while (p) {
+        pid[nb] = atoi(p);
+        if (pid[nb++] <= 0) {
+            return;
+        }
+        if (nb >= 16) {
+            return;
+        }
+        p = strtok(NULL, " ");
+    }
+    /* get all pid's info */
+    while (--nb >= 0) {
+        unsigned long long data;
+        /* read values from /proc/pid/stat */
+        sprintf(filename, PID_STAT, pid[nb]);
+        if ((fp = fopen(filename, "r")) == NULL) {
+            return;
+        }
+        unsigned long long cpudata[4];
+        if (fgets(line, 256, fp) == NULL) {
+            fclose(fp);
+            return;
+        }
+
+        if ((p = strstr(line, ")")) == NULL) {
+            fclose(fp);
+            return;
+        }
+        if (sscanf(p, "%*s %*c %*d %*d %*d %*d %*d %*u %*u %*u %*u %*u %llu %llu %llu %llu",
+                    &cpudata[0], &cpudata[1], &cpudata[2], &cpudata[3]) == EOF) {
+            fclose(fp);
+            return;
+        }
+        st_proc.user_cpu += cpudata[0];
+        st_proc.user_cpu += cpudata[2];
+        st_proc.sys_cpu += cpudata[1];
+        st_proc.sys_cpu += cpudata[3];
+        fclose(fp);
+        /* get cpu&mem info from /proc/pid/status */
+        sprintf(filename, PID_STATUS, pid[nb]);
+        if ((fp = fopen(filename, "r")) == NULL) {
+            return;
+        }
+        while (fgets(line, 256, fp) != NULL) {
+            if (!strncmp(line, "VmRSS:", 6)) {
+                sscanf(line + 6, "%llu", &data);
+                st_proc.mem += data * 1024;
+            }
+        }
+        fclose(fp);
+        /* get io info from /proc/pid/io */
+        sprintf(filename, PID_IO, pid[nb]);
+        if ((fp = fopen(filename, "r")) == NULL) {
+            return;
+        }
+        while (fgets(line, 256, fp) != NULL) {
+            if (!strncmp(line, "read_bytes:", 11)) {
+                sscanf(line + 11, "%llu", &data);
+                st_proc.read_bytes += data;
+            }
+            else if (!strncmp(line, "write_bytes:", 12)) {
+                sscanf(line + 12, "%llu", &data);
+                st_proc.write_bytes += data;
+            }
+        }
+        fclose(fp);
+    }
+
+    /* read+calc cpu total time from /proc/stat */
+    fp = fopen("/proc/stat", "r");
+    if (fp == NULL) {
+        fclose(fp);
+        return;
+    }
+    unsigned long long cpu_time[10];
+    bzero(cpu_time, sizeof(cpu_time));
+    if (fscanf(fp, "%*s %llu %llu %llu %llu %llu %llu %llu %llu %llu %llu",
+                &cpu_time[0], &cpu_time[1], &cpu_time[2], &cpu_time[3],
+                &cpu_time[4], &cpu_time[5], &cpu_time[6], &cpu_time[7],
+                &cpu_time[8], &cpu_time[9]) == EOF) {
+        fclose(fp);
+        return;
+    }
+    fclose(fp);
+    int i;
+    for(i=0; i < 10;i++) {
+        st_proc.total_cpu += cpu_time[i];
+    }
+    /* read total mem from /proc/meminfo */
+    fp = fopen("/proc/meminfo", "r");
+    if (fp == NULL) {
+        fclose(fp);
+        return;
+    }
+    if (fscanf(fp, "MemTotal:      %llu kB", &st_proc.total_mem) == EOF) {
+        fclose(fp);
+        return;
+    }
+    st_proc.total_mem *= 1024;
+    fclose(fp);
+    /* store data to tsar */
+    int pos = sprintf(buf, "%lld,%lld,%lld,%lld,%lld,%lld,%lld",
+            st_proc.user_cpu,
+            st_proc.sys_cpu,
+            st_proc.total_cpu,
+            st_proc.total_mem,
+            st_proc.mem,
+            st_proc.read_bytes,
+            st_proc.write_bytes
+            );
+    if (pos >= 0) buf[pos] = '\0';
+    set_mod_record(mod, buf);
+}
+
+static void
+set_proc_record(struct module *mod, double st_array[],
+    U_64 pre_array[], U_64 cur_array[], int inter)
+{
+    if (cur_array[2] > pre_array[2]) {
+        st_array[2] = cur_array[2] - pre_array[2];
+    } else {
+        st_array[2] = 0;
+        return;
+    }
+    if (cur_array[0] >= pre_array[0]) {
+        st_array[0] = (cur_array[0] - pre_array[0]) * 100.0 / st_array[2];
+    } else {
+        st_array[0] = 0;
+    }
+    if (cur_array[1] >= pre_array[1]) {
+        st_array[1] = (cur_array[1] - pre_array[1]) * 100.0 / st_array[2];
+    } else {
+        st_array[1] = 0;
+    }
+    st_array[3] = cur_array[4] * 100.0 / cur_array[3];
+    st_array[4] = cur_array[4];
+    if (cur_array[5] >= pre_array[5]) {
+        st_array[5] = (cur_array[5] - pre_array[5]) * 1.0 / inter;
+    } else {
+        st_array[5] = 0;
+    }
+    if (cur_array[6] >= pre_array[6]) {
+        st_array[6] = (cur_array[6] - pre_array[6]) * 1.0 / inter;
+    } else {
+        st_array[5] = 0;
+    }
+}
+
+static struct mod_info proc_info[] = {
+    {"  user", SUMMARY_BIT,  0,  STATS_NULL},
+    {"   sys", SUMMARY_BIT,  0,  STATS_NULL},
+    {" total", HIDE_BIT,  0,  STATS_NULL},
+    {"   mem", SUMMARY_BIT,  0,  STATS_NULL},
+    {"   RSS", DETAIL_BIT,  0,  STATS_NULL},
+    {"  read", DETAIL_BIT,  0,  STATS_NULL},
+    {" write", DETAIL_BIT,  0,  STATS_NULL},
+};
+
+void
+mod_register(struct module *mod)
+{
+    register_mod_fields(mod, "--proc", proc_usage, proc_info, 7, read_proc_stats, set_proc_record);
+}
diff --git a/modules/mod_rndc.c b/modules/mod_rndc.c
deleted file mode 100644
index 8a54a87..0000000
--- a/modules/mod_rndc.c
+++ /dev/null
@@ -1,179 +0,0 @@
-/* rndc: Remote Name Daemon Controller
-   daoxian, 2011-11-8
-   Copyright(C) Taobao Inc.
- */
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include "tsar.h"
-
-
-static char *rndc_usage = "    --rndc               information for rndc stats";
-static char g_buf[10240];
-
-static void create_script()
-{
-	const char *script = ""
-		"#!/usr/bin/perl\n"
-		"use strict;\n"
-		"\n"
-		"my $stat_file_name = get_stat_file_name('/usr/local/pharos/conf/named.conf');\n"
-		"# my @label_arr = ('++ Socket I/O Statistics ++', '++ Incoming Requests ++', '++ Incoming Queries ++', '++ Name Server Statistics ++');\n"
-		"my @label_arr = ('++ Incoming Requests ++', '++ Name Server Statistics ++');\n"
-		"# my %display_key_hash = ('QUERY' => 'query', 'A' => 'address', 'CNAME' => 'cname', 'NS' => 'ns', 'SOA' => 'soa');\n"
-		"my %display_key_hash = ('QUERY' => 'qps', 'response time 0ms to 5ms' => 'rt_05', 'response time 5ms to 10ms' => 'rt_10', 'response time 10ms to 20ms' => 'rt_20', 'response time 20ms to 50ms' => 'rt_50',  'response time 50ms to Xms' => 'rt_50+');\n"
-		"my %result = ();\n"
-		"\n"
-		"foreach my $label (@label_arr)\n"
-		"{\n"
-		"	my @stat_arr = get_stat_section($stat_file_name, $label);\n"
-		"	foreach my $stat_result (@stat_arr)\n"
-		"	{\n"
-		"		$stat_result =~ m|^\\s*(\\d+)\\s+(.+?)\\s*$|;\n"
-		"		my $display_key = get_display_key($2);\n"
-		"		$result{$display_key} = $1 if $display_key;\n"
-		"	}\n"
-		"}\n"
-		"foreach my $k (keys %display_key_hash)\n"
-		"{\n"
-		"	$result{$display_key_hash{$k}} = 0 if not defined($result{$display_key_hash{$k}});\n"
-		"}\n"
-		"\n"
-		"foreach my $k (sort keys %result)\n"
-		"{\n"
-		"	my $v = $result{$k};\n"
-		"	print \"$k,$v\\n\";\n"
-		"}\n"
-		"\n"
-		"sub get_display_key\n"
-		"{\n"
-		"	my $key = shift;\n"
-		"	if ($display_key_hash{$key})\n"
-		"	{\n"
-		"		return $display_key_hash{$key};\n"
-		"	}\n"
-		"	else\n"
-		"	{\n"
-		"		# my $ret = '';\n"
-		"		# map { $ret .= lc(substr($_, 0, 1)); } split /\\s+/, $key;\n"
-		"		# return $ret;\n"
-		"		return '';\n"
-		"	}\n"
-		"}\n"
-		"\n"
-		"\n"
-		"sub get_stat_file_name\n"
-		"{\n"
-		"	my $conf_file = shift;\n"
-		"	open FH, $conf_file or die \"error open file: $conf_file\\n\";\n"
-		"	my @arr = <FH>;\n"
-		"	close FH;\n"
-		"	@arr = grep /\\bstatistics-file\\b/, @arr;\n"
-		"	$arr[0] =~ m|\\s*statistics-file\\s+[\"'](.+)[\"']\\s*;|;\n"
-		"	return $1 ? $1 : '';\n"
-		"}\n"
-		"\n"
-		"\n"
-		"sub get_stat_section\n"
-		"{\n"
-		"	my $stat_file = shift;\n"
-		"	my $seperator = shift;\n"
-		"\n"
-		"	open FH, $stat_file or die \"error open file: $stat_file\\n\";\n"
-		"	my @stat_arr = <FH>;\n"
-		"	close FH;\n"
-		"	my $stat_str = join \"\", @stat_arr;\n"
-		"	$stat_str =~ s/\\r/\\n/g;\n"
-		"	$stat_str =~ m/\\Q$seperator\\E\\n+((.|\\n)*?)\\n+\\+\\+/;\n"
-		"	my $val = $1;\n"
-		"	$val =~ s/\\n\\s+/\\n/g;\n"
-		"	$val =~ s/^\\s+//g;\n"
-		"	return split /\\n/, $val;\n"
-		"}\n";
-
-	FILE *fp = fopen("/tmp/rndc_tsar.pl", "w");
-	if (!fp)
-		return;
-	fputs(script, fp);
-	fclose(fp);
-}
-
-static void exec_script()
-{
-	system("/usr/local/pharos/sbin/rndc -c /usr/local/pharos/conf/trndc.conf stats");
-	system("perl /tmp/rndc_tsar.pl > /tmp/rndc_tsar.txt");
-	system("echo -n 'badvs,' >> /tmp/rndc_tsar.txt; MYSQL_BIN=`/bin/rpm -ql mysql|/bin/egrep -e '/bin/mysql$'` && ${MYSQL_BIN} -ss -uroot -Ddns_config -e 'SELECT COUNT(name) FROM vs WHERE in_use=1 AND available=0' >> /tmp/rndc_tsar.txt");
-	//system("rm -f /tmp/rndc_tsar.pl");
-}
-
-static void parse_stat_file(char buf[])
-{
-	FILE *fp = fopen("/tmp/rndc_tsar.txt", "r");
-	if (!fp)
-		return;
-
-	rewind(fp);
-	int pos = 0;
-	char line[LEN_128];
-	while (fgets(line, LEN_128, fp))
-	{
-		char *s = strtok(line, ","); // key
-		if (!s)
-			continue;
-		s = strtok(NULL, ",");  // value
-		if (!s)
-			continue;
-		if (strlen(s) > 0)
-			s[strlen(s) - 1] = '\0';  // get rid of '\n'
-		pos += sprintf(buf + pos, "%s,", s);
-	}
-	fclose(fp);
-	system("rm /tmp/rndc_tsar.txt");
-
-	if (pos > 0)
-		buf[pos - 1] = '\0';
-	else
-		buf[pos] = '\0';
-}
-
-static void read_rndc_stats(struct module *mod)
-{
-	memset(g_buf, 0, sizeof(g_buf));
-	create_script();
-	exec_script();	
-	parse_stat_file(g_buf);
-	set_mod_record(mod, g_buf);
-}
-
-
-static void set_rndc_stats(struct module *mod, double st_array[],
-		U_64 pre_array[], U_64 cur_array[], int inter)
-{
-	int i;
-	for (i = 0; i < 6; i ++)
-	{
-		if(cur_array[i] >= pre_array[i])
-			st_array[i] = (cur_array[i] - pre_array[i]) / inter;
-		else
-			st_array[i] = 0;
-	}
-	st_array[6] = cur_array[i];
-}
-
-static struct mod_info rndc_info[] = {
-	{"   qps", SUMMARY_BIT,MERGE_NULL,  STATS_NULL},
-	{" rt_05", DETAIL_BIT, MERGE_NULL,  STATS_NULL},
-	{" rt_10", DETAIL_BIT, MERGE_NULL,  STATS_NULL},
-	{" rt_20", DETAIL_BIT, MERGE_NULL,  STATS_NULL},
-	{" rt_50", DETAIL_BIT, MERGE_NULL,  STATS_NULL},
-	{"rt_50+", DETAIL_BIT, MERGE_NULL,  STATS_NULL},
-	{"badvs",  DETAIL_BIT, MERGE_NULL,  STATS_NULL},
-};
-
-void mod_register(struct module *mod)
-{
-	register_mod_fileds(mod, "--rndc", rndc_usage, rndc_info, sizeof(rndc_info) / sizeof(struct mod_info), read_rndc_stats, set_rndc_stats);
-}
-
-
diff --git a/modules/mod_squid.c b/modules/mod_squid.c
index b22f219..63c9779 100644
--- a/modules/mod_squid.c
+++ b/modules/mod_squid.c
@@ -18,54 +18,54 @@
 char *squid_usage = "    --squid             Squid utilities";
 
 struct stats_squid {
-	int usable;
-	struct squid_counters
-	{
-		struct counters_client {
-			unsigned long long http_requests;
-			unsigned long long http_hits;
-			unsigned long long http_kbytes_out;
-			unsigned long long http_hit_kbytes_out;
-
-		} cc;
-		struct counters_server {
-			unsigned long long all_requests;
-			unsigned long long all_kbytes_in;
-			unsigned long long all_kbytes_out;
-		} cs;
-	} sc;
-	struct squid_info {
-		struct mem_usage {
-			unsigned long long mem_total;
-			unsigned long long mem_free;
-			unsigned long long mem_size;
-		} mu;
-		struct fd_usage {
-			unsigned int fd_used;
-			unsigned int fd_queue;
-		} fu;
-		struct info_internal_data {
-			unsigned int entries;
-			unsigned int memobjs;
-			unsigned int hotitems;
-		} iid;
-		struct squid_float {
-			unsigned long long meanobjsize;
-			unsigned long long responsetime;
-			unsigned long long disk_hit;
-			unsigned long long mem_hit;
-			unsigned long long http_hit_rate;
-			unsigned long long byte_hit_rate;
-		} sf;
-	} si;
-} ;
+    int usable;
+    struct squid_counters
+    {
+        struct counters_client {
+            unsigned long long http_requests;
+            unsigned long long http_hits;
+            unsigned long long http_kbytes_out;
+            unsigned long long http_hit_kbytes_out;
+
+        } cc;
+        struct counters_server {
+            unsigned long long all_requests;
+            unsigned long long all_kbytes_in;
+            unsigned long long all_kbytes_out;
+        } cs;
+    } sc;
+    struct squid_info {
+        struct mem_usage {
+            unsigned long long mem_total;
+            unsigned long long mem_free;
+            unsigned long long mem_size;
+        } mu;
+        struct fd_usage {
+            unsigned int fd_used;
+            unsigned int fd_queue;
+        } fu;
+        struct info_internal_data {
+            unsigned int entries;
+            unsigned int memobjs;
+            unsigned int hotitems;
+        } iid;
+        struct squid_float {
+            unsigned long long meanobjsize;
+            unsigned long long responsetime;
+            unsigned long long disk_hit;
+            unsigned long long mem_hit;
+            unsigned long long http_hit_rate;
+            unsigned long long byte_hit_rate;
+        } sf;
+    } si;
+};
 
 
 #define STATS_SQUID_SIZE (sizeof(struct stats_squid))
 #define MAXSQUID 10
 
-/* 
- * here we defined a pointer to a array of structure 
+/*
+ * here we defined a pointer to a array of structure
  * we should call the member like:
  *
  *              (*(s_st_squid + p_idx))[idx].member
@@ -76,8 +76,8 @@ struct stats_squid {
 struct stats_squid  s_st_squid[MAXSQUID];
 
 struct p_squid_info {
-	struct squid_counters *scp;
-	struct squid_info * sip;
+    struct squid_counters *scp;
+    struct squid_info * sip;
 };
 
 #define DIGITS "0123456789"
@@ -87,208 +87,229 @@ struct p_squid_info {
 #define MAXINT 2147483647
 
 char *key[] = {
-	"client_http.requests",
-	"client_http.hits",
-	"client_http.kbytes_out",
-	"client_http.hit_kbytes_out"
+    "client_http.requests",
+    "client_http.hits",
+    "client_http.kbytes_out",
+    "client_http.hit_kbytes_out"
 };
 
 char *key_info[] = {
-	"Total in use",
-	"Total free",
-	"Total size",
-	"Number of file desc currently in use",
-	"Files queued for open",
-	"StoreEntries",
-	"StoreEntries with MemObjects",
-	"Hot Object Cache Items",
-	"Mean Object Size",
+    "Total in use",
+    "Total free",
+    "Total size",
+    "Number of file desc currently in use",
+    "Files queued for open",
+    "StoreEntries",
+    "StoreEntries with MemObjects",
+    "Hot Object Cache Items",
+    "Mean Object Size",
 };
 
 char *key_float[] = {
-	"Average HTTP respone time",
-	"Mean Object Size:",
-	"Request Memory Hit Ratios:",
-	"Request Filesystem Hit Ratios:",
-	"Request Hit Ratios:",
-	"Byte Hit Ratios:",
-	"Request Disk Hit Ratios:",
+    "Average HTTP respone time",
+    "Mean Object Size:",
+    "Request Memory Hit Ratios:",
+    "Request Filesystem Hit Ratios:",
+    "Request Hit Ratios:",
+    "Byte Hit Ratios:",
+    "Request Disk Hit Ratios:",
+    "HTTP Requests (All):",
 };
 
-char *a_trim(char *str, int len)
+char *
+a_trim(char *str, int len)
 {
-	char *dest, *l_str;
-	dest = (char *)malloc(len);
-	int i = 0;
-	l_str = str;
-	if (l_str == NULL)
-		return NULL;
-	while (*l_str++ != '\0' && len--) {
-		if(*l_str != ' ' && *l_str != '\t')
-			dest[i++] = *l_str;
-	}
-	dest[i] = '\0';
-	return dest;
+    int    i = 0;
+    char  *dest = NULL, *l_str;
+    dest = (char *)malloc(len);
+    if (dest == NULL ){
+        return NULL;
+    }
+    l_str = str;
+    if (l_str == NULL) {
+        free(dest);
+        return NULL;
+    }
+    while (*l_str++ != '\0' && len--) {
+        if (*l_str != ' ' && *l_str != '\t') {
+            dest[i++] = *l_str;
+        }
+    }
+    dest[i] = '\0';
+    return dest;
 }
-int read_a_int_value(char *buf,
-		char *key,
-		unsigned int *ret,
-		int type) 
+
+int
+read_a_int_value(char *buf, char *key, unsigned int *ret, int type)
 {
-	int k;
-	char *tmp;
-	/* is str match the keywords? */
-	if ((tmp = strstr(buf, key)) != NULL) {
-
-		/* is number befor the key string? */
-		if (type == LEFT) {
-			tmp = buf;
-		}		
-		/* compute the offset */	
-		k = strcspn(tmp, DIGITS);
-		sscanf(tmp + k, "%d", ret);
-		return 1;
-	} else 	return 0;
+    int    k;
+    char  *tmp;
+    /* is str match the keywords? */
+    if ((tmp = strstr(buf, key)) != NULL) {
+        /* is number befor the key string? */
+        if (type == LEFT) {
+            tmp = buf;
+        }
+        /* compute the offset */
+        k = strcspn(tmp, DIGITS);
+        sscanf(tmp + k, "%d", ret);
+        return 1;
+
+    } else {
+        return 0;
+    }
 }
 
-int read_a_long_long_value(char *buf, 
-		char *key, 
-		unsigned long long *ret,
-		int type)
+int
+read_a_long_long_value(char *buf, char *key, unsigned long long *ret, int type)
 {
-	int k;
-	char *tmp;
-	/* is str match the keywords? */
-	if ((tmp = strstr(buf, key)) != NULL) {
-
-		/* is number befor the key string? */
-		if (type == LEFT) {
-			tmp = buf;
-		}		
-		/* compute the offset */
-		k = strcspn(tmp, DIGITS);
-		sscanf(tmp + k, "%lld", ret);
-		return 1;
-	} else return 0;
+    int    k;
+    char  *tmp;
+    /* is str match the keywords? */
+    if ((tmp = strstr(buf, key)) != NULL) {
+
+        /* is number befor the key string? */
+        if (type == LEFT) {
+            tmp = buf;
+        }
+        /* compute the offset */
+        k = strcspn(tmp, DIGITS);
+        sscanf(tmp + k, "%lld", ret);
+        return 1;
+
+    } else {
+        return 0;
+    }
 }
+
 /*add for squidclient when counter is nagtive*/
-int read_a_long_long_value_squid(char *buf, 
-		char *key, 
-		unsigned long long *ret,
-		int type)
+int
+read_a_long_long_value_squid(char *buf, char *key, unsigned long long *ret, int type)
 {
-	int k;
-	char *tmp;
-	/* is str match the keywords? */
-	if ((tmp = strstr(buf, key)) != NULL) {
-
-		/* is number befor the key string? */
-		if (type == LEFT) {
-			tmp = buf;
-		}		
-		/* compute the offset */
-		k = strcspn(tmp, SQUIDDIGITS);
-		sscanf(tmp + k, "%lld", ret);
-		if(*ret > MAXINT)
-			*ret += MAXINT;
-		return 1;
-	} else return 0;
+    int    k;
+    char  *tmp;
+    /* is str match the keywords? */
+    if ((tmp = strstr(buf, key)) != NULL) {
+
+        /* is number befor the key string? */
+        if (type == LEFT) {
+            tmp = buf;
+        }
+        /* compute the offset */
+        k = strcspn(tmp, SQUIDDIGITS);
+        sscanf(tmp + k, "%lld", ret);
+        if (*ret > MAXINT) {
+            *ret += MAXINT;
+        }
+        return 1;
+
+    } else {
+        return 0;
+    }
 }
 
-int read_a_float_value(char *buf, 
-		char *key, 
-		unsigned long long *ret,
-		int type,
-		int len)
+int
+read_a_float_value(char *buf, char *key, unsigned long long *ret, int type, int len)
 {
-	int k;
-	int r, l;
-	char *tmp;
-	char *tmp2;
-	/* is str match the keywords? */
-	if ((tmp = strstr(buf, key)) != NULL) {
-
-		/* is number befor the key string? */
-		if (type == LEFT) {
-			tmp = buf;
-		}		
-		/* skip the trial number like 5min:*/
-		if((tmp2 = strstr(tmp, "min")) != NULL)
-			tmp = tmp2;
-		/* compute the offset */
-		k = strcspn(tmp, DIGITS);
-		sscanf(tmp + k, "%d.%d", &r, &l);
-		*ret = (unsigned long long)r * len + l;
-		return 1;
-	} else return 0;
+    int    k;
+    int    r, l;
+    char  *tmp;
+    char  *tmp2;
+    /* is str match the keywords? */
+    if ((tmp = strstr(buf, key)) != NULL) {
+
+        /* is number befor the key string? */
+        if (type == LEFT) {
+            tmp = buf;
+        }
+        /* skip the trial number like 5min:*/
+        if ((tmp2 = strstr(tmp, "min")) != NULL) {
+            tmp = tmp2;
+        }
+        /* compute the offset */
+        k = strcspn(tmp, DIGITS);
+        sscanf(tmp + k, "%d.%d", &r, &l);
+        *ret = (unsigned long long)r * len + l;
+        return 1;
+
+    } else {
+        return 0;
+    }
 }
 
-
-void collect_cnts(char *l, struct squid_counters *sc)
+void
+collect_cnts(char *l, struct squid_counters *sc)
 {
-	read_a_long_long_value_squid(l, key[0],
-			&sc->cc.http_requests, RIGHT);
+    read_a_long_long_value_squid(l, key[0],
+            &sc->cc.http_requests, RIGHT);
 
-	read_a_long_long_value(l, key[1], 
-			&sc->cc.http_hits, RIGHT);
+    read_a_long_long_value(l, key[1],
+            &sc->cc.http_hits, RIGHT);
 
-	read_a_long_long_value(l, key[2],
-			&sc->cc.http_kbytes_out, RIGHT);
+    read_a_long_long_value(l, key[2],
+            &sc->cc.http_kbytes_out, RIGHT);
 
-	read_a_long_long_value(l, key[3],
-			&sc->cc.http_hit_kbytes_out, RIGHT);
+    read_a_long_long_value(l, key[3],
+            &sc->cc.http_hit_kbytes_out, RIGHT);
 }
 
 
-void collect_info(char *l, struct squid_info *si)
+void
+collect_info(char *l, struct squid_info *si)
 {
-	read_a_long_long_value(l, key_info[0], 
-			&si->mu.mem_total, RIGHT);
-
-	read_a_long_long_value(l, key_info[1],
-			&si->mu.mem_free, RIGHT);
-
-	read_a_long_long_value(l, key_info[2],
-			&si->mu.mem_size, RIGHT);
-
-	read_a_int_value(l, key_info[3], 
-			&si->fu.fd_used, RIGHT);
-
-	read_a_int_value(l, key_info[4],
-			&si->fu.fd_queue, RIGHT);
-
-	/* here don't confuse the order */
-	if (read_a_int_value(l, key_info[6], 
-				&si->iid.memobjs, LEFT)) return;
-
-	read_a_int_value(l, key_info[5],
-			&si->iid.entries, LEFT);
-
-	read_a_int_value(l, key_info[7],
-			&si->iid.hotitems, LEFT);
-
-	read_a_float_value(l, key_float[0],
-			&si->sf.responsetime, 
-			RIGHT, 100);
-
-	read_a_float_value(l, key_float[1],
-			&si->sf.meanobjsize, 
-			RIGHT, 100);
-	read_a_float_value(l, key_float[3],
-			&si->sf.disk_hit, 
-			RIGHT, 10);
-	read_a_float_value(l, key_float[2],
-			&si->sf.mem_hit, 
-			RIGHT, 10);
-	read_a_float_value(l, key_float[4],
-			&si->sf.http_hit_rate, 
-			RIGHT, 10);
-	read_a_float_value(l, key_float[5],
-			&si->sf.byte_hit_rate, 
-			RIGHT, 10);
-	read_a_float_value(l, key_float[6],
-			&si->sf.disk_hit, 
-			RIGHT, 10);
+    read_a_long_long_value(l, key_info[0],
+            &si->mu.mem_total, RIGHT);
+
+    read_a_long_long_value(l, key_info[1],
+            &si->mu.mem_free, RIGHT);
+
+    read_a_long_long_value(l, key_info[2],
+            &si->mu.mem_size, RIGHT);
+
+    read_a_int_value(l, key_info[3],
+            &si->fu.fd_used, RIGHT);
+
+    read_a_int_value(l, key_info[4],
+            &si->fu.fd_queue, RIGHT);
+
+    /* here don't confuse the order */
+    if (read_a_int_value(l, key_info[6],
+                &si->iid.memobjs, LEFT))
+    {
+        return;
+    }
+
+    read_a_int_value(l, key_info[5],
+            &si->iid.entries, LEFT);
+
+    read_a_int_value(l, key_info[7],
+            &si->iid.hotitems, LEFT);
+
+    read_a_float_value(l, key_float[0],
+            &si->sf.responsetime,
+            RIGHT, 100);
+
+    read_a_float_value(l, key_float[1],
+            &si->sf.meanobjsize,
+            RIGHT, 100);
+    read_a_float_value(l, key_float[3],
+            &si->sf.disk_hit,
+            RIGHT, 10);
+    read_a_float_value(l, key_float[2],
+            &si->sf.mem_hit,
+            RIGHT, 10);
+    read_a_float_value(l, key_float[4],
+            &si->sf.http_hit_rate,
+            RIGHT, 10);
+    read_a_float_value(l, key_float[5],
+            &si->sf.byte_hit_rate,
+            RIGHT, 10);
+    read_a_float_value(l, key_float[6],
+            &si->sf.disk_hit,
+            RIGHT, 10);
+    read_a_float_value(l, key_float[7],
+            &si->sf.responsetime,
+            RIGHT, 100000);
 
 }
 
@@ -297,318 +318,339 @@ int port_list[MAXSQUID] = {0};
 static int squid_nr = 0;
 static int live_squid_nr = 0;
 
-void count_squid_nr()
+void
+count_squid_nr()
 {
-	DIR *dp;
-	struct dirent *dirp;
-	char *s_token, *e_token;
-	static char tmp_s_port[32] = {0};
-	squid_nr = 0;
-	if (!(dp = opendir("/etc/squid/")))
-		return;
-	while ((dirp = readdir(dp)))
-	{ 
-		s_token = strstr(dirp->d_name, "squid.");
-		if (s_token) {
-			e_token = strstr(s_token + 6, ".conf");
-			if (e_token && *(e_token + 5) == '\0') {
-				memset(tmp_s_port, 0, sizeof(tmp_s_port));
-				memcpy(tmp_s_port, s_token + 6, e_token - s_token - 6);
-				port_list[squid_nr++] = atoi(tmp_s_port);
-			}
-		}
-	}
-	if(squid_nr > MAXSQUID)
-		squid_nr = MAXSQUID;
-	closedir(dp);
+    DIR            *dp;
+    char           *s_token, *e_token;
+    static char     tmp_s_port[32] = {0};
+    struct dirent  *dirp;
+    squid_nr = 0;
+    if (!(dp = opendir("/etc/squid/"))) {
+        return;
+    }
+    while ((dirp = readdir(dp)))
+    {
+        s_token = strstr(dirp->d_name, "squid.");
+        if (s_token) {
+            e_token = strstr(s_token + 6, ".conf");
+            if (e_token && *(e_token + 5) == '\0') {
+                memset(tmp_s_port, 0, sizeof(tmp_s_port));
+                memcpy(tmp_s_port, s_token + 6, e_token - s_token - 6);
+                port_list[squid_nr++] = atoi(tmp_s_port);
+            }
+        }
+    }
+    if (squid_nr > MAXSQUID) {
+        squid_nr = MAXSQUID;
+    }
+    closedir(dp);
 }
 
 
-	ssize_t
+ssize_t
 mywrite(int fd, void *buf, size_t len)
 {
-	return send(fd, buf, len, 0);
+    return send(fd, buf, len, 0);
 }
 
-	ssize_t
+ssize_t
 myread(int fd, void *buf, size_t len)
 {
-	return recv(fd, buf, len, 0);
+    return recv(fd, buf, len, 0);
 }
 
-	int
-client_comm_connect(int sock, const char *dest_host, 
-		u_short dest_port, struct timeval *tvp)
+int
+client_comm_connect(int sock, const char *dest_host, u_short dest_port, struct timeval *tvp)
 {
-	const struct hostent *hp = NULL;
-	struct sockaddr_in to_addr;
-	int	flags, res;
-	fd_set	fdr, fdw;
-	struct	timeval timeout;
-
-	/* set socket fd noblock */
-	if((flags = fcntl(sock, F_GETFL, 0)) < 0)
-		return -1;
-
-	if(fcntl(sock, F_SETFL, flags | O_NONBLOCK) < 0)
-		return -1;
-
-	/* Set up the destination socket address for message to send to. */
-	if (hp == NULL) {
-		to_addr.sin_family = AF_INET;
-
-		if ((hp = gethostbyname(dest_host)) == 0)
-			return (-1);
-		memcpy(&to_addr.sin_addr, hp->h_addr, hp->h_length);
-		to_addr.sin_port = htons(dest_port);
-	}
-	if (connect(sock, (struct sockaddr *) &to_addr, sizeof(struct sockaddr_in)) != 0) {
-		if (errno != EINPROGRESS) // EINPROGRESS
-			return -1;
-		else
-			goto select;
-	}
-	else
-		return -1;
+    int                    flags, res;
+    fd_set                 fdr, fdw;
+    struct  timeval        timeout;
+    struct sockaddr_in     to_addr;
+    const struct hostent  *hp = NULL;
+
+    /* set socket fd noblock */
+    if ((flags = fcntl(sock, F_GETFL, 0)) < 0) {
+        return -1;
+    }
+
+    if (fcntl(sock, F_SETFL, flags | O_NONBLOCK) < 0) {
+        return -1;
+    }
+
+    /* Set up the destination socket address for message to send to. */
+    if (hp == NULL) {
+        to_addr.sin_family = AF_INET;
+
+        if ((hp = gethostbyname(dest_host)) == 0)
+            return (-1);
+        memcpy(&to_addr.sin_addr, hp->h_addr, hp->h_length);
+        to_addr.sin_port = htons(dest_port);
+    }
+    if (connect(sock, (struct sockaddr *) &to_addr, sizeof(struct sockaddr_in)) != 0) {
+        if (errno != EINPROGRESS) {
+            return -1;
+
+        } else {
+            goto select;
+        }
+
+    } else {
+        return -1;
+    }
 select:
-	FD_ZERO(&fdr);
-	FD_ZERO(&fdw);
-	FD_SET(sock, &fdr);
-	FD_SET(sock, &fdw);
-
-	timeout.tv_sec = 10;
-	timeout.tv_usec = 0;
-
-	res = select(sock + 1, &fdr, &fdw, NULL, &timeout);
-	if(res < 0){
-		return -1;
-	}
-	else if(res == 0){
-		return -1;
-	}
-	else{
-		return 1;
-	}
+    FD_ZERO(&fdr);
+    FD_ZERO(&fdw);
+    FD_SET(sock, &fdr);
+    FD_SET(sock, &fdw);
+
+    timeout.tv_sec = 10;
+    timeout.tv_usec = 0;
+
+    res = select(sock + 1, &fdr, &fdw, NULL, &timeout);
+    if (res < 0) {
+        return -1;
+
+    } else if (res == 0) {
+        return -1;
+
+    } else {
+        return 1;
+    }
 }
 
-int parse_squid_info(char *buf, char *cmd, struct p_squid_info *p_si)
+int
+parse_squid_info(char *buf, char *cmd, struct p_squid_info *p_si)
 {
-	char *line;
-	line = strtok(buf, "\n");
-
-	while(line != NULL) {
-		if(!strcmp(cmd, "counters"))
-			collect_cnts(line, p_si->scp);
-		else if (!strcmp(cmd, "info")) {
-			collect_info(line, p_si->sip);
-		} else {
-			fprintf(stderr, "unknown command\n");
-			return -1;
-		}
-		line = strtok(NULL, "\n");
-	}
-
-	if(!strcmp(cmd, "counters") && p_si->scp->cc.http_requests == 0){
-		return -1;
-	}
-	if(!strcmp(cmd, "info") && p_si->sip->sf.responsetime == 0){
-		return -1;
-	}
-	return 0;
+    char *line;
+    line = strtok(buf, "\n");
+
+    while (line != NULL) {
+        if (!strcmp(cmd, "counters")) {
+            collect_cnts(line, p_si->scp);
+
+        } else if (!strcmp(cmd, "info")) {
+            collect_info(line, p_si->sip);
+
+        } else {
+            fprintf(stderr, "unknown command\n");
+            return -1;
+        }
+        line = strtok(NULL, "\n");
+    }
+
+    if (!strcmp(cmd, "counters") && p_si->scp->cc.http_requests == 0) {
+        return -1;
+    }
+    if (!strcmp(cmd, "info") && p_si->sip->sf.responsetime == 0) {
+        /* return -1;*/
+    }
+    return 0;
 }
 
-int __get_squid_info(char *squidoption,
-		char *squidcmd, 
-		int port, int index)
+int
+__get_squid_info(char *squidoption, char *squidcmd, int port, int index)
 {
-	char buf[LEN_4096];
-	char *hostname = "localhost";
-	int len, conn, bytesWritten, fsize = 0;
-	struct p_squid_info psi = {&s_st_squid[index].sc, &s_st_squid[index].si};
-
-	if ((conn = socket(PF_INET, SOCK_STREAM, 0)) < 0) {
-		close(conn);
-		return -1;
-	}
-	if (client_comm_connect(conn, hostname, port, NULL) < 0) {
-		close(conn);
-		return -1;
-	}
-	int flags;
-	/* set socket fd noblock */
-	if((flags = fcntl(conn, F_GETFL, 0)) < 0) {
-		close(conn);
-		return -1;
-	}
-	if(fcntl(conn, F_SETFL, flags & ~O_NONBLOCK) < 0) {
-		close(conn);
-		return -1;
-	}
-	struct timeval timeout = {10, 0}; 
-	setsockopt(conn, SOL_SOCKET, SO_SNDTIMEO, (char *)&timeout, sizeof(struct timeval));
-	setsockopt(conn, SOL_SOCKET, SO_RCVTIMEO, (char *)&timeout, sizeof(struct timeval));
-
-	bytesWritten = mywrite(conn, squidcmd, strlen(squidcmd));
-	if (bytesWritten < 0) {
-		close(conn);
-		return -2;
-	} else if (bytesWritten != strlen(squidcmd)) {
-		close(conn);
-		return -3;
-	}
-	while ((len = myread(conn, buf, sizeof(buf))) > 0) {
-		fsize += len;
-	}
-	/* read error */
-	if (fsize < 1000) {
-		close(conn);
-		return -1;
-	}
-
-	if (parse_squid_info(buf, squidoption, &psi) < 0) {
-		close(conn);
-		return -1;
-	}
-	close(conn);
-	return 0;
+    char buf[LEN_4096];
+    char *hostname = "localhost";
+    int len, conn, bytesWritten, fsize = 0;
+    struct p_squid_info psi = {&s_st_squid[index].sc, &s_st_squid[index].si};
+
+    if ((conn = socket(PF_INET, SOCK_STREAM, 0)) < 0) {
+        close(conn);
+        return -1;
+    }
+    if (client_comm_connect(conn, hostname, port, NULL) < 0) {
+        close(conn);
+        return -1;
+    }
+    int flags;
+    /* set socket fd noblock */
+    if ((flags = fcntl(conn, F_GETFL, 0)) < 0) {
+        close(conn);
+        return -1;
+    }
+    if (fcntl(conn, F_SETFL, flags & ~O_NONBLOCK) < 0) {
+        close(conn);
+        return -1;
+    }
+    struct timeval timeout = {10, 0};
+    setsockopt(conn, SOL_SOCKET, SO_SNDTIMEO, (char *)&timeout, sizeof(struct timeval));
+    setsockopt(conn, SOL_SOCKET, SO_RCVTIMEO, (char *)&timeout, sizeof(struct timeval));
+
+    bytesWritten = mywrite(conn, squidcmd, strlen(squidcmd));
+    if (bytesWritten < 0) {
+        close(conn);
+        return -2;
+
+    } else if (bytesWritten != strlen(squidcmd)) {
+        close(conn);
+        return -3;
+    }
+    while ((len = myread(conn, buf, sizeof(buf) - fsize -1)) > 0) {
+        fsize += len;
+    }
+    buf[fsize] = '\0';
+    /* read error */
+    if (fsize < 1000) {
+        close(conn);
+        return -1;
+    }
+
+    if (parse_squid_info(buf, squidoption, &psi) < 0) {
+        close(conn);
+        return -1;
+    }
+    close(conn);
+    return 0;
 
 }
 
-int __read_squid_stat(int port,int index)
+int
+__read_squid_stat(int port, int index)
 {
-	int i;
-	/* fullfil the raw infomation here 
-	   for each port */
-	char *options[2] = {"info", "counters"};
-	char msg[2][LEN_512];
-
-	/* we have two command 'info' & 'counters' to run */
-	for(i = 0; i < 2; i++) {
-		//msg[i]=(char *)malloc(LEN_512);
-		sprintf(msg[i],
-				"GET cache_object://localhost/%s "
-				"HTTP/1.1\r\n"
-				"Host: localhost\r\n"
-				"Accept:*/*\r\n"
-				"Connection: close\r\n\r\n",
-				options[i]);
-		if(__get_squid_info(options[i], msg[i], port, index) < 0) {
-			return -1;
-		}
-		//free(msg[i]);
-	}
-	return 0;
+    int i;
+    /* fullfil the raw infomation here
+       for each port */
+    char *options[2] = {"info", "counters"};
+    char msg[2][LEN_512];
+
+    /* we have two command 'info' & 'counters' to run */
+    for (i = 0; i < 2; i++) {
+        sprintf(msg[i],
+                "GET cache_object://localhost/%s "
+                "HTTP/1.1\r\n"
+                "Host: localhost\r\n"
+                "Accept:*/*\r\n"
+                "Connection: close\r\n\r\n",
+                options[i]);
+        if (__get_squid_info(options[i], msg[i], port, index) < 0) {
+            return -1;
+        }
+    }
+    return 0;
 }
 
-int store_single_port(char *buf, char *itemname, int i) 
+int
+store_single_port(char *buf, char *itemname, int i)
 {
-	int len = 0;
-	len += sprintf(buf, "%s=", itemname);
-	/* print single port info to buffer here */
-	len += sprintf(buf + len, 
-			"%llu,%llu,%llu,%llu,%llu,%llu,"
-			"%u,%u,%u,%u,%u,%llu,%u,%u",
-			s_st_squid[i].sc.cc.http_requests,
-			s_st_squid[i].si.sf.responsetime,
-			s_st_squid[i].si.sf.http_hit_rate,
-			s_st_squid[i].si.sf.byte_hit_rate,
-			s_st_squid[i].si.sf.disk_hit,
-			s_st_squid[i].si.sf.mem_hit,
-			s_st_squid[i].si.fu.fd_used,
-			s_st_squid[i].si.fu.fd_queue,
-			s_st_squid[i].si.iid.entries,
-			s_st_squid[i].si.iid.memobjs,
-			s_st_squid[i].si.iid.hotitems,
-			s_st_squid[i].si.sf.meanobjsize,
-			squid_nr,
-			live_squid_nr);
-	return len;
+    int len = 0;
+    len += sprintf(buf, "%s=", itemname);
+    /* print single port info to buffer here */
+    len += sprintf(buf + len,
+            "%llu,%llu,%llu,%llu,%llu,%llu,"
+            "%u,%u,%u,%u,%u,%llu,%u,%u",
+            s_st_squid[i].sc.cc.http_requests,
+            s_st_squid[i].si.sf.responsetime,
+            s_st_squid[i].si.sf.http_hit_rate,
+            s_st_squid[i].si.sf.byte_hit_rate,
+            s_st_squid[i].si.sf.disk_hit,
+            s_st_squid[i].si.sf.mem_hit,
+            s_st_squid[i].si.fu.fd_used,
+            s_st_squid[i].si.fu.fd_queue,
+            s_st_squid[i].si.iid.entries,
+            s_st_squid[i].si.iid.memobjs,
+            s_st_squid[i].si.iid.hotitems,
+            s_st_squid[i].si.sf.meanobjsize,
+            squid_nr,
+            live_squid_nr);
+    return len;
 }
 
-
-void read_squid_stat(struct module *mod)
+void
+read_squid_stat(struct module *mod, char *parameter)
 {
-	int i, pos = 0;
-	char buf[LEN_4096] = {0};
-	char itemname[LEN_4096] = {0};
-	live_squid_nr = 0;
-
-	if (squid_nr == 0) {
-		count_squid_nr();
-		if (squid_nr == 0 ) return;
-	}
-	memset(s_st_squid, 0, STATS_SQUID_SIZE * MAXSQUID);
-	/*get the live squid number*/
-	for(i = 0; i < squid_nr; i++) {
-		int retry = 0;
-		/* read on each port and retry to get squidclient for 3 times*/
-		while(__read_squid_stat(port_list[i],i) < 0 && retry < RETRY_NUM) 
-		{
-			retry++;
-		}
-		if(retry == RETRY_NUM) {
-			continue;
-		}
-		s_st_squid[i].usable = TRUE;
-		live_squid_nr++;
-	}
-
-	/* traverse the port list */
-	for(i = 0; i < squid_nr; i++) {
-		if(!s_st_squid[i].usable)
-			continue;
-		/* generate the item name */
-		int n = sprintf(itemname, "port%d", port_list[i]);
-		itemname[n] = '\0';
-
-		/* print log to buffer */
-		pos += store_single_port(buf + pos, itemname, i);
-		/* print a seperate char */
-		pos += sprintf(buf + pos, ITEM_SPLIT);
-	}
-	if(pos && squid_nr == live_squid_nr) {
-		buf[pos] = '\0';
-		set_mod_record(mod, buf);
-	}
+    int i, pos = 0;
+    char buf[LEN_4096] = {0};
+    char itemname[LEN_4096] = {0};
+    live_squid_nr = 0;
+
+    count_squid_nr();
+    if (squid_nr == 0) {
+        if (atoi(parameter) != 0) {
+            port_list[0] = atoi(parameter);  
+            squid_nr = 1;
+        } else {
+            port_list[0] = 3128;
+            squid_nr = 1;
+        }
+    }
+
+    memset(s_st_squid, 0, STATS_SQUID_SIZE * MAXSQUID);
+    /*get the live squid number*/
+    for (i = 0; i < squid_nr; i++) {
+        int retry = 0;
+        /* read on each port and retry to get squidclient for 3 times*/
+        while (__read_squid_stat(port_list[i], i) < 0 && retry < RETRY_NUM) {
+            retry++;
+        }
+        if (retry == RETRY_NUM) {
+            continue;
+        }
+        s_st_squid[i].usable = TRUE;
+        live_squid_nr++;
+    }
+
+    /* traverse the port list */
+    for (i = 0; i < squid_nr; i++) {
+        if (!s_st_squid[i].usable) {
+            continue;
+        }
+        /* generate the item name */
+        int n = sprintf(itemname, "port%d", port_list[i]);
+        itemname[n] = '\0';
+
+        /* print log to buffer */
+        pos += store_single_port(buf + pos, itemname, i);
+        /* print a seperate char */
+        pos += sprintf(buf + pos, ITEM_SPLIT);
+    }
+    if (pos && squid_nr == live_squid_nr) {
+        buf[pos] = '\0';
+        set_mod_record(mod, buf);
+    }
 }
 
 
-static void set_squid_record(struct module *mod, double st_array[],
-		U_64 pre_array[], U_64 cur_array[], int inter)
+static void
+set_squid_record(struct module *mod, double st_array[], U_64 pre_array[], U_64 cur_array[], int inter)
 {
-	int i;
-
-	/* set st record */
-	if(cur_array[0] >= pre_array[0])
-		st_array[0] = (cur_array[0] - pre_array[0]) / inter;
-	else
-		st_array[0] = 0;
-	st_array[1] = cur_array[1] / 100.0;
-	for (i = 2; i <=  5; i++) st_array[i] = cur_array[i] / 10.0;
-	for (i = 6; i <= 10; i++) st_array[i] = cur_array[i];
-	st_array[11] = (cur_array[11] << 10) / 100.0;
-	st_array[12] = cur_array[12];
-	st_array[13] = cur_array[13];
+    int i;
+
+    /* set st record */
+    if (cur_array[0] >= pre_array[0]) {
+        st_array[0] = (cur_array[0] - pre_array[0]) / inter;
+
+    } else {
+        st_array[0] = 0;
+    }
+    st_array[1] = cur_array[1] / 100.0;
+    for (i = 2; i <=  5; i++) st_array[i] = cur_array[i] / 10.0;
+    for (i = 6; i <= 10; i++) st_array[i] = cur_array[i];
+    st_array[11] = (cur_array[11] << 10) / 100.0;
+    st_array[12] = cur_array[12];
+    st_array[13] = cur_array[13];
 }
 
 static struct mod_info s_info[] = {
-	{"   qps", SUMMARY_BIT,  MERGE_SUM,  STATS_SUB_INTER},
-	{"    rt", DETAIL_BIT, MERGE_AVG,  STATS_NULL},
-	{" r_hit", DETAIL_BIT, MERGE_AVG,  STATS_NULL},
-	{" b_hit", DETAIL_BIT, MERGE_AVG,  STATS_NULL},
-	{" d_hit", DETAIL_BIT, MERGE_AVG,  STATS_NULL},
-	{" m_hit", DETAIL_BIT, MERGE_AVG,  STATS_NULL},
-	{"fdused", DETAIL_BIT, MERGE_SUM,  STATS_NULL},
-	{" fdque", DETAIL_BIT, MERGE_SUM,  STATS_NULL},
-	{"  objs", DETAIL_BIT, MERGE_SUM,  STATS_NULL},
-	{" inmem", DETAIL_BIT, MERGE_SUM,  STATS_NULL},
-	{"   hot", DETAIL_BIT, MERGE_SUM,  STATS_NULL},
-	{"  size", DETAIL_BIT, MERGE_AVG,  STATS_NULL},
-	{"totalp", DETAIL_BIT, MERGE_AVG,  STATS_NULL},
-	{" livep", DETAIL_BIT, MERGE_AVG,  STATS_NULL}
+    {"   qps", SUMMARY_BIT,  MERGE_SUM,  STATS_SUB_INTER},
+    {"    rt", DETAIL_BIT, MERGE_AVG,  STATS_NULL},
+    {" r_hit", DETAIL_BIT, MERGE_AVG,  STATS_NULL},
+    {" b_hit", DETAIL_BIT, MERGE_AVG,  STATS_NULL},
+    {" d_hit", DETAIL_BIT, MERGE_AVG,  STATS_NULL},
+    {" m_hit", DETAIL_BIT, MERGE_AVG,  STATS_NULL},
+    {"fdused", DETAIL_BIT, MERGE_SUM,  STATS_NULL},
+    {" fdque", DETAIL_BIT, MERGE_SUM,  STATS_NULL},
+    {"  objs", DETAIL_BIT, MERGE_SUM,  STATS_NULL},
+    {" inmem", DETAIL_BIT, MERGE_SUM,  STATS_NULL},
+    {"   hot", DETAIL_BIT, MERGE_SUM,  STATS_NULL},
+    {"  size", DETAIL_BIT, MERGE_AVG,  STATS_NULL},
+    {"totalp", DETAIL_BIT, MERGE_AVG,  STATS_NULL},
+    {" livep", DETAIL_BIT, MERGE_AVG,  STATS_NULL}
 };
 
-void mod_register(struct module *mod)
+void
+mod_register(struct module *mod)
 {
-	register_mod_fileds(mod, "--squid", squid_usage, s_info, 14, read_squid_stat, set_squid_record);
+    register_mod_fields(mod, "--squid", squid_usage, s_info, 14, read_squid_stat, set_squid_record);
 }
diff --git a/modules/mod_swap.c b/modules/mod_swap.c
index e56b539..4dbbc65 100644
--- a/modules/mod_swap.c
+++ b/modules/mod_swap.c
@@ -1,8 +1,10 @@
 #include "tsar.h"
 
-struct stats_swap{
-	unsigned long pswpin;
-	unsigned long pswpout;
+struct stats_swap {
+    unsigned long long pswpin;
+    unsigned long long pswpout;
+    unsigned long long swaptotal;
+    unsigned long long swapfree;
 };
 
 
@@ -11,44 +13,88 @@ struct stats_swap{
 static char *swap_usage = "    --swap              swap usage";
 
 /*
- *********************************************
- * Read swapping statistics from /proc/vmstat.
- *********************************************
+ *************************************************************
+ * Read swapping statistics from /proc/vmstat & /proc/meminfo.
+ *************************************************************
  */
-static void read_vmstat_swap(struct module *mod)
+static void
+read_vmstat_swap(struct module *mod)
 {
-	FILE *fp;
-	char line[4096], buf[LEN_4096];
-	memset(buf, 0, LEN_4096);
-	struct stats_swap st_swap;
-	memset(&st_swap, 0, sizeof(struct stats_swap));
-	if ((fp = fopen(VMSTAT, "r")) == NULL) {
-		return ;
-	}
+    FILE              *fp;
+    char               line[LEN_4096], buf[LEN_4096];
+    struct stats_swap  st_swap;
+
+    memset(buf, 0, LEN_4096);
+    memset(&st_swap, 0, sizeof(struct stats_swap));
+    /* read /proc/vmstat*/
+    if ((fp = fopen(VMSTAT, "r")) == NULL) {
+        return ;
+    }
+
+    while (fgets(line, LEN_4096, fp) != NULL) {
+
+        if (!strncmp(line, "pswpin ", 7)) {
+            /* Read number of swap pages brought in */
+            sscanf(line + 7, "%llu", &st_swap.pswpin);
 
-	while (fgets(line, LEN_4096, fp) != NULL) {
+        } else if (!strncmp(line, "pswpout ", 8)) {
+            /* Read number of swap pages brought out */
+            sscanf(line + 8, "%llu", &st_swap.pswpout);
+        }
+    }
+    fclose(fp);
+    /* read /proc/meminfo */
+    if ((fp = fopen(MEMINFO, "r")) == NULL) {
+        return;
+    }
 
-		if (!strncmp(line, "pswpin ", 7)) {
-			/* Read number of swap pages brought in */
-			sscanf(line + 7, "%lu", &st_swap.pswpin);
-		}
-		else if (!strncmp(line, "pswpout ", 8)) {
-			/* Read number of swap pages brought out */
-			sscanf(line + 8, "%lu", &st_swap.pswpout);
-		}
+    while (fgets(line, LEN_4096, fp) != NULL) {
+        if (!strncmp(line, "SwapTotal:", 10)) {
+	    sscanf(line + 10, "%llu", &st_swap.swaptotal);
+
+	} else if (!strncmp(line, "SwapFree:", 9)) {
+	    sscanf(line + 9, "%llu", &st_swap.swapfree);
 	}
-	fclose(fp);
-	int pos = sprintf(buf, "%ld,%ld", st_swap.pswpin, st_swap.pswpout);
-	buf[pos] = '\0';
-	set_mod_record(mod, buf);
-	return;
+    }
+    fclose(fp);
+
+    sprintf(buf, "%lld,%lld,%lld,%lld", st_swap.pswpin, st_swap.pswpout, st_swap.swaptotal*1024, st_swap.swapfree*1024);
+    set_mod_record(mod, buf);
+    return;
+}
+
+static void
+set_swap_record(struct module *mod, double st_array[],
+    U_64 pre_array[], U_64 cur_array[], int inter)
+{
+    if (cur_array[0] >= pre_array[0]) {
+        st_array[0] = (cur_array[0] -  pre_array[0]) / inter;
+
+    } else {
+        st_array[0] = 0;
+    }
+
+    if (cur_array[1] >= pre_array[1]) {
+        st_array[1] = (cur_array[1] -  pre_array[1]) / inter;
+
+    } else {
+        st_array[1] = 0;
+    }
+
+    /* calc total swap and use util */
+    st_array[2] = cur_array[2];
+    st_array[3] = 100.0 - cur_array[3] * 100.0 / cur_array[2];
 }
+
 static struct mod_info swap_info[] = {
-	{" swpin", DETAIL_BIT,  0,  STATS_SUB_INTER},
-	{"swpout", DETAIL_BIT,  0,  STATS_SUB_INTER}
+    {" swpin", DETAIL_BIT,  0,  STATS_NULL},
+    {"swpout", DETAIL_BIT,  0,  STATS_NULL},
+    {" total", DETAIL_BIT,  0,  STATS_NULL},
+    {"  util", DETAIL_BIT,  0,  STATS_NULL}
 };
 
-void mod_register(struct module *mod)
+void
+mod_register(struct module *mod)
 {
-	register_mod_fileds(mod, "--swap", swap_usage, swap_info, 2, read_vmstat_swap, NULL);
+    register_mod_fields(mod, "--swap", swap_usage, swap_info, 4, read_vmstat_swap, set_swap_record);
 }
diff --git a/modules/mod_swift.c b/modules/mod_swift.c
deleted file mode 100644
index eb6de71..0000000
--- a/modules/mod_swift.c
+++ /dev/null
@@ -1,314 +0,0 @@
-#include <sys/socket.h>
-#include <fcntl.h>
-#include <string.h>
-#include "tsar.h"
-
-
-#define RETRY_NUM 3
-/* swift default port should not changed */
-#define HOSTNAME "localhost"
-#define PORT 81
-#define EQUAL ":="
-#define DEBUG 1
-
-char *swift_usage = "    --swift             Swift object storage infomation";
-int mgrport=81;
-
-/* string at swiftclient -p 81 mgr:info */
-/*
- * Average HTTP respone time:      5min: 11.70 ms, 60min: 10.06 ms
- * Request Hit Ratios:     5min: 95.8%, 60min: 95.7%
- * Byte Hit Ratios:        5min: 96.6%, 60min: 96.6%
- * UP Time:        247256.904 seconds
- * CPU Time:       23487.042 seconds
- * StoreEntries           : 20776287
- * client_http.requests = 150291472
- * client_http.bytes_in = 6380253436
- * client_http.bytes_out = 5730106537327
- */
-const static char *SWIFT_STORE[] = {
-	"client_http.requests",
-	"client_http.bytes_in",
-	"client_http.bytes_out",
-	"StoreEntries"
-};
-
-/* struct for swift counters */
-struct status_swift {
-	unsigned long long requests;
-	unsigned long long rt;
-	unsigned long long r_hit;
-	unsigned long long b_hit;
-	unsigned long long objs;
-	unsigned long long bytes_in;
-	unsigned long long bytes_out;
-	unsigned long long t_cpu;
-	unsigned long long s_cpu;
-} stats;
-
-/* swift register info for tsar */
-struct mod_info swift_info[] = {
-	{"   qps", DETAIL_BIT,  0,  STATS_NULL},
-	{"    rt", DETAIL_BIT,  0,  STATS_NULL},
-	{" r_hit", DETAIL_BIT,  0,  STATS_NULL},
-	{" b_hit", DETAIL_BIT,  0,  STATS_NULL},
-	{"  objs", DETAIL_BIT,  0,  STATS_NULL},
-	{" in_bw", DETAIL_BIT,  0,  STATS_NULL},
-	{"out_bw", DETAIL_BIT,  0,  STATS_NULL},
-	{"   cpu", DETAIL_BIT,  0,  STATS_NULL},
-	{"  null", HIDE_BIT,  0,  STATS_NULL}
-};
-/* opens a tcp or udp connection to a remote host or local socket */
-int my_swift_net_connect(const char *host_name, int port, int *sd, char* proto)
-{
-	struct sockaddr_in servaddr;
-	struct protoent *ptrp;
-	int result;
-
-	bzero((char *)&servaddr,sizeof(servaddr));
-	servaddr.sin_family=AF_INET;
-	servaddr.sin_port=htons(port);
-	inet_pton(AF_INET, host_name, &servaddr.sin_addr);
-
-	/* map transport protocol name to protocol number */
-	if(((ptrp=getprotobyname(proto)))==NULL){
-		if(DEBUG)
-			printf("Cannot map \"%s\" to protocol number\n",proto);
-		return 3;
-	}
-
-	/* create a socket */
-	*sd=socket(PF_INET,(!strcmp(proto,"udp"))?SOCK_DGRAM:SOCK_STREAM,ptrp->p_proto);
-	if(*sd<0){
-		close(*sd);
-		if(DEBUG)
-			printf("Socket creation failed\n");
-		return 3;
-	}
-	/* open a connection */
-	result=connect(*sd,(struct sockaddr *)&servaddr,sizeof(servaddr));
-	if(result<0){
-		close(*sd);
-		switch(errno){
-			case ECONNREFUSED:
-				if(DEBUG)
-					printf("Connection refused by host\n");
-				break;
-			case ETIMEDOUT:
-				if(DEBUG)
-					printf("Timeout while attempting connection\n");
-				break;
-			case ENETUNREACH:
-				if(DEBUG)
-					printf("Network is unreachable\n");
-				break;
-			default:
-				if(DEBUG)
-					printf("Connection refused or timed out\n");
-		}
-
-		return 2;
-	}
-	return 0;
-}
-ssize_t mywrite_swift(int fd, void *buf, size_t len)
-{
-	return send(fd, buf, len, 0);
-}
-
-ssize_t myread_swift(int fd, void *buf, size_t len)
-{
-	return recv(fd, buf, len, 0);
-}
-
-/* get value from counter */
-int read_swift_value(char *buf,
-		const char *key,
-		unsigned long long *ret)
-{
-	int k=0;
-	char *tmp;
-	/* is str match the keywords? */
-	if ((tmp = strstr(buf, key)) != NULL) {
-		/* compute the offset */
-		k = strcspn(tmp, EQUAL);
-		sscanf(tmp + k + 1, "%lld", ret);
-		return 1;
-	} else return 0;
-}
-int parse_swift_info(char *buf)
-{
-	char *line;
-	line = strtok(buf, "\n");
-	while(line != NULL){
-		read_swift_value(line, SWIFT_STORE[0], &stats.requests);
-		read_swift_value(line, SWIFT_STORE[1], &stats.bytes_in);
-		read_swift_value(line, SWIFT_STORE[2], &stats.bytes_out);
-		read_swift_value(line, SWIFT_STORE[3], &stats.objs);
-		/*Average HTTP respone time:      5min: 11.70 ms, 60min: 10.06 ms*/
-		if(strstr(line,"Average HTTP respone time") != NULL){
-			float a,b;
-			sscanf(line,"        Average HTTP respone time:      5min: %f ms, 60min: %f ms",&a,&b);
-			stats.rt = a * 1000;
-		}
-		/* Request Hit Ratios:     5min: 95.8%, 60min: 95.7% */
-		if(strstr(line,"Request Hit Ratios") != NULL){
-			float a,b;
-			sscanf(line,"        Request Hit Ratios:     5min: %f%%, 60min: %f%%",&a,&b);
-			stats.r_hit = a * 1000;
-		}
-		/* Byte Hit Ratios:        5min: 96.6%, 60min: 96.6% */
-		if(strstr(line,"Byte Hit Ratios") != NULL){
-			float a,b;
-			sscanf(line,"        Byte Hit Ratios:        5min: %f%%, 60min: %f%%",&a,&b);
-			stats.b_hit = a * 1000 + b;
-		}
-		/* UP Time:        247256.904 seconds */
-		if(strstr(line,"UP Time") != NULL){
-			float a;
-			sscanf(line,"        UP Time:        %f seconds",&a);
-			stats.t_cpu = a * 1000;
-		}
-		/* CPU Time:       23487.042 seconds */
-		if(strstr(line,"CPU Time") != NULL){
-			float a;
-			sscanf(line,"        CPU Time:       %f seconds",&a);
-			stats.s_cpu = a * 1000;
-		}
-		line = strtok(NULL, "\n");
-	}
-	return 0;
-}
-
-void set_swift_record(struct module *mod, double st_array[],
-		U_64 pre_array[], U_64 cur_array[], int inter)
-{
-	//qps
-	if(cur_array[0] >= pre_array[0])
-		st_array[0] = (cur_array[0] -  pre_array[0]) / inter;
-	else
-		st_array[0] = -1;
-	//rt
-	st_array[1] = cur_array[1]*1.0/1000;
-	//r_hit b_hit
-	st_array[2] = cur_array[2]*1.0/1000;
-	st_array[3] = cur_array[3]*1.0/1000;
-	//objs
-	st_array[4] = cur_array[4];
-	//in_bw out_bw
-	if(cur_array[5] >= pre_array[5])
-		st_array[5] = (cur_array[5] -  pre_array[5]) / inter;
-	else
-		st_array[5] = -1;
-	if(cur_array[6] >= pre_array[6])
-		st_array[6] = (cur_array[6] -  pre_array[6]) / inter;
-	else
-		st_array[6] = -1;
-	//cpu
-	if(cur_array[7] > pre_array[7] && cur_array[8] >= pre_array[8])
-		st_array[7] = (cur_array[8] - pre_array[8]) * 100.0 / (cur_array[7] - pre_array[7]);
-	else
-		st_array[7] = -1;
-}
-
-int read_swift_stat(char *cmd)
-{
-	char msg[LEN_512];
-	char buf[LEN_4096];
-	sprintf(msg,
-			"GET cache_object://localhost/%s "
-			"HTTP/1.1\r\n"
-			"Host: localhost\r\n"
-			"Accept:*/*\r\n"
-			"Connection: close\r\n\r\n",
-			cmd);
-
-	int len, conn, bytesWritten, fsize = 0;
-
-	if(my_swift_net_connect(HOSTNAME, mgrport, &conn, "tcp") != 0){
-		close(conn);
-		return -1;
-	}
-
-	int flags;
-
-	/* set socket fd noblock */
-	if((flags = fcntl(conn, F_GETFL, 0)) < 0) {
-		close(conn);
-		return -1;
-	}
-
-	if(fcntl(conn, F_SETFL, flags & ~O_NONBLOCK) < 0) {
-		close(conn);
-		return -1;
-	}
-
-	struct timeval timeout = {10, 0};
-
-	setsockopt(conn, SOL_SOCKET, SO_SNDTIMEO, (char *)&timeout, sizeof(struct timeval));
-
-	setsockopt(conn, SOL_SOCKET, SO_RCVTIMEO, (char *)&timeout, sizeof(struct timeval));
-
-	bytesWritten = mywrite_swift(conn, msg, strlen(msg));
-	if (bytesWritten < 0) {
-		close(conn);
-		return -2;
-	} else if (bytesWritten != strlen(msg)) {
-		close(conn);
-		return -3;
-	}
-
-	while ((len = myread_swift(conn, buf, sizeof(buf))) > 0) {
-		fsize += len;
-	}
-
-	/* read error */
-	if (fsize < 100) {
-		close(conn);
-		return -1;
-	}
-
-	if (parse_swift_info(buf) < 0) {
-		close(conn);
-		return -1;
-	}
-
-	close(conn);
-	return 0;
-}
-
-void read_swift_stats(struct module *mod, char *parameter)
-{
-	int retry = 0 ,pos = 0;
-	char buf[LEN_1024];
-	memset(&stats, 0, sizeof(stats));
-	mgrport = atoi(parameter);
-	if(!mgrport){
-		mgrport = 81;
-	}
-	while(read_swift_stat("info") < 0 && retry < RETRY_NUM){
-		retry++;
-	}
-	retry = 0;
-	while(read_swift_stat("counters") < 0 && retry < RETRY_NUM){
-		retry++;
-	}
-	pos = sprintf(buf, "%lld,%lld,%lld,%lld,%lld,%lld,%lld,%lld,%lld",
-			stats.requests,
-			stats.rt,
-			stats.r_hit,
-			stats.b_hit,
-			stats.objs,
-			stats.bytes_in,
-			stats.bytes_out,
-			stats.t_cpu,
-			stats.s_cpu
-		     );
-	buf[pos] = '\0';
-	set_mod_record(mod, buf);
-}
-
-void mod_register(struct module *mod)
-{
-	register_mod_fileds(mod, "--swift", swift_usage, swift_info, 9, read_swift_stats, set_swift_record);
-}
diff --git a/modules/mod_swift_code.c b/modules/mod_swift_code.c
deleted file mode 100644
index 50103bc..0000000
--- a/modules/mod_swift_code.c
+++ /dev/null
@@ -1,292 +0,0 @@
-#include <sys/socket.h>
-#include <fcntl.h>
-#include "tsar.h"
-
-
-#define RETRY_NUM 3
-/* swift default port should not changed */
-#define HOSTNAME "localhost"
-#define PORT 81
-#define EQUAL "="
-#define DEBUG 0
-
-char *swift_code_usage = "    --swift_code             Swift httpcode";
-int mgrport = 81;
-
-/* httpcode string at swiftclient -p 81 mgr:counters */
-/*
-   http status code 200 = 223291656
-   http status code 204 = 54
-   http status code 206 = 25473
-   http status code 302 = 299
-   http status code 304 = 29595013
-   http status code 400 = 159
-   http status code 403 = 50675
-   http status code 404 = 1261657
-   http status code 500 = 51
-   http status code 502 = 5
-   http status code 503 = 229
-   http status code 504 = 213
-   http status code other = 8981
- */
-const static char *SWIFT_CODE[] = {
-	"http status code 200",
-	"http status code 206",
-	"http status code 301",
-	"http status code 302",
-	"http status code 304",
-	"http status code 400",
-	"http status code 403",
-	"http status code 404",
-	"http status code 500",
-	"http status code 502",
-	"http status code 503",
-	"http status code 504",
-	"http status code other"
-};
-
-/* struct for httpcode counters */
-struct status_swift_code {
-	unsigned long long code200;
-	unsigned long long code206;
-	unsigned long long code301;
-	unsigned long long code302;
-	unsigned long long code304;
-	unsigned long long code400;
-	unsigned long long code403;
-	unsigned long long code404;
-	unsigned long long code500;
-	unsigned long long code502;
-	unsigned long long code503;
-	unsigned long long code504;
-	unsigned long long codeother;
-} stats;
-
-/* swift register info for tsar */
-struct mod_info swift_code_info[] = {
-	{"   200", DETAIL_BIT,  0,  STATS_NULL},
-	{"   206", DETAIL_BIT,  0,  STATS_NULL},
-	{"   301", DETAIL_BIT,  0,  STATS_NULL},
-	{"   302", DETAIL_BIT,  0,  STATS_NULL},
-	{"   304", DETAIL_BIT,  0,  STATS_NULL},
-	{"   400", DETAIL_BIT,  0,  STATS_NULL},
-	{"   403", DETAIL_BIT,  0,  STATS_NULL},
-	{"   404", DETAIL_BIT,  0,  STATS_NULL},
-	{"   500", DETAIL_BIT,  0,  STATS_NULL},
-	{"   502", DETAIL_BIT,  0,  STATS_NULL},
-	{"   503", DETAIL_BIT,  0,  STATS_NULL},
-	{"   504", DETAIL_BIT,  0,  STATS_NULL},
-	{" other", DETAIL_BIT,  0,  STATS_NULL},
-};
-/* opens a tcp or udp connection to a remote host or local socket */
-int my_swift_code_net_connect(const char *host_name, int port, int *sd, char* proto)
-{
-	struct sockaddr_in servaddr;
-	struct protoent *ptrp;
-	int result;
-
-	bzero((char *)&servaddr,sizeof(servaddr));
-	servaddr.sin_family=AF_INET;
-	servaddr.sin_port=htons(port);
-	inet_pton(AF_INET, host_name, &servaddr.sin_addr);
-
-	/* map transport protocol name to protocol number */
-	if(((ptrp=getprotobyname(proto)))==NULL){
-		if(DEBUG)
-			printf("Cannot map \"%s\" to protocol number\n",proto);
-		return 3;
-	}
-
-	/* create a socket */
-	*sd=socket(PF_INET,(!strcmp(proto,"udp"))?SOCK_DGRAM:SOCK_STREAM,ptrp->p_proto);
-	if(*sd<0){
-		close(*sd);
-		if(DEBUG)
-			printf("Socket creation failed\n");
-		return 3;
-	}
-	/* open a connection */
-	result=connect(*sd,(struct sockaddr *)&servaddr,sizeof(servaddr));
-	if(result<0){
-		close(*sd);
-		switch(errno){
-			case ECONNREFUSED:
-				if(DEBUG)
-					printf("Connection refused by host\n");
-				break;
-			case ETIMEDOUT:
-				if(DEBUG)
-					printf("Timeout while attempting connection\n");
-				break;
-			case ENETUNREACH:
-				if(DEBUG)
-					printf("Network is unreachable\n");
-				break;
-			default:
-				if(DEBUG)
-					printf("Connection refused or timed out\n");
-		}
-
-		return 2;
-	}
-	return 0;
-}
-ssize_t mywrite_swift_code(int fd, void *buf, size_t len)
-{
-	return send(fd, buf, len, 0);
-}
-
-ssize_t myread_swift_code(int fd, void *buf, size_t len)
-{
-	return recv(fd, buf, len, 0);
-}
-
-/* get value from counter */
-int read_swift_code_value(char *buf,
-		const char *key,
-		unsigned long long *ret)
-{
-	int k=0;
-	char *tmp;
-	/* is str match the keywords? */
-	if ((tmp = strstr(buf, key)) != NULL) {
-		/* compute the offset */
-		k = strcspn(tmp, EQUAL);
-		sscanf(tmp + k + 1, "%lld", ret);
-		return 1;
-	} else return 0;
-}
-int parse_swift_code_info(char *buf)
-{
-	char *line;
-	line = strtok(buf, "\n");
-	while(line != NULL){
-		read_swift_code_value(line, SWIFT_CODE[0], &stats.code200);
-		read_swift_code_value(line, SWIFT_CODE[1], &stats.code206);
-		read_swift_code_value(line, SWIFT_CODE[2], &stats.code301);
-		read_swift_code_value(line, SWIFT_CODE[3], &stats.code302);
-		read_swift_code_value(line, SWIFT_CODE[4], &stats.code304);
-		read_swift_code_value(line, SWIFT_CODE[5], &stats.code400);
-		read_swift_code_value(line, SWIFT_CODE[6], &stats.code403);
-		read_swift_code_value(line, SWIFT_CODE[7], &stats.code404);
-		read_swift_code_value(line, SWIFT_CODE[8], &stats.code500);
-		read_swift_code_value(line, SWIFT_CODE[9], &stats.code502);
-		read_swift_code_value(line, SWIFT_CODE[10], &stats.code503);
-		read_swift_code_value(line, SWIFT_CODE[11], &stats.code504);
-		read_swift_code_value(line, SWIFT_CODE[12], &stats.codeother);
-		line = strtok(NULL, "\n");
-	}
-	return 0;
-}
-
-void set_swift_code_record(struct module *mod, double st_array[],
-		U_64 pre_array[], U_64 cur_array[], int inter)
-{
-	int i;
-	for (i = 0; i < mod->n_col; i++) {
-		if (cur_array[i] >= pre_array[i]) {
-			st_array[i] = (cur_array[i] - pre_array[i]) * 1.0 / inter;
-		}
-	}
-}
-
-int read_swift_code_stat()
-{
-	char msg[LEN_512];
-	char buf[LEN_4096];
-	sprintf(msg,
-			"GET cache_object://localhost/counters "
-			"HTTP/1.1\r\n"
-			"Host: localhost\r\n"
-			"Accept:*/*\r\n"
-			"Connection: close\r\n\r\n");
-
-	int len, conn, bytesWritten, fsize = 0;
-
-	if(my_swift_code_net_connect(HOSTNAME, mgrport, &conn, "tcp") != 0){
-		close(conn);
-		return -1;
-	}
-
-	int flags;
-
-	/* set socket fd noblock */
-	if((flags = fcntl(conn, F_GETFL, 0)) < 0) {
-		close(conn);
-		return -1;
-	}
-
-	if(fcntl(conn, F_SETFL, flags & ~O_NONBLOCK) < 0) {
-		close(conn);
-		return -1;
-	}
-
-	struct timeval timeout = {10, 0};
-
-	setsockopt(conn, SOL_SOCKET, SO_SNDTIMEO, (char *)&timeout, sizeof(struct timeval));
-
-	setsockopt(conn, SOL_SOCKET, SO_RCVTIMEO, (char *)&timeout, sizeof(struct timeval));
-
-	bytesWritten = mywrite_swift_code(conn, msg, strlen(msg));
-	if (bytesWritten < 0) {
-		close(conn);
-		return -2;
-	} else if (bytesWritten != strlen(msg)) {
-		close(conn);
-		return -3;
-	}
-
-	while ((len = myread_swift_code(conn, buf, sizeof(buf))) > 0) {
-		fsize += len;
-	}
-
-	/* read error */
-	if (fsize < 100) {
-		close(conn);
-		return -1;
-	}
-
-	if (parse_swift_code_info(buf) < 0) {
-		close(conn);
-		return -1;
-	}
-
-	close(conn);
-	return 0;
-}
-
-void read_swift_code_stats(struct module *mod, char *parameter)
-{
-	int retry = 0 ,pos = 0;
-	char buf[LEN_1024];
-	memset(&stats, 0, sizeof(stats));
-	mgrport = atoi(parameter);
-	if(!mgrport){
-		mgrport = 81;
-	}
-	while(read_swift_code_stat() < 0 && retry < RETRY_NUM){
-		retry++;
-	}
-	pos = sprintf(buf, "%lld,%lld,%lld,%lld,%lld,%lld,%lld,%lld,%lld,%lld,%lld,%lld,%lld",
-			stats.code200,
-			stats.code206,
-			stats.code301,
-			stats.code302,
-			stats.code304,
-			stats.code400,
-			stats.code403,
-			stats.code404,
-			stats.code500,
-			stats.code502,
-			stats.code503,
-			stats.code504,
-			stats.codeother
-		     );
-	buf[pos] = '\0';
-	set_mod_record(mod, buf);
-}
-
-void mod_register(struct module *mod)
-{
-	register_mod_fileds(mod, "--swift_code", swift_code_usage, swift_code_info, 13, read_swift_code_stats, set_swift_code_record);
-}
diff --git a/modules/mod_swift_fwd.c b/modules/mod_swift_fwd.c
deleted file mode 100644
index 6b82232..0000000
--- a/modules/mod_swift_fwd.c
+++ /dev/null
@@ -1,244 +0,0 @@
-#include <sys/socket.h>
-#include <fcntl.h>
-#include "tsar.h"
-
-
-#define RETRY_NUM 3
-/* swift default port should not changed */
-#define HOSTNAME "localhost"
-#define PORT 81
-#define EQUAL "="
-#define DEBUG 0
-
-char *swift_fwd_usage = "    --swift_fwd             Swift source infomation";
-int mgrport = 81;
-
-/* swiftclient -p 81 mgr:counters */
-/*
-   server_http.requests = 13342113
-   server_http.errors = 220
-   server_http.bytes_in = 210982517709
-   server_http.bytes_out = 0
-   server_http.svc_time = 1526450363
- */
-const static char *SWIFT_FWD[] = {
-	"server_http.requests",
-	"server_http.errors",
-	"server_http.bytes_in",
-	"server_http.svc_time"
-};
-
-/* struct for httpfwd counters */
-struct status_swift_fwd {
-	unsigned long long requests;
-	unsigned long long errors;
-	unsigned long long bytes_in;
-	unsigned long long svc_time;
-} stats;
-
-/* swift register info for tsar */
-struct mod_info swift_fwd_info[] = {
-	{"   qps", DETAIL_BIT,  0,  STATS_NULL},
-	{" traff", DETAIL_BIT,  0,  STATS_NULL},
-	{" error", DETAIL_BIT,  0,  STATS_NULL},
-	{"    rt", DETAIL_BIT,  0,  STATS_NULL}
-};
-/* opens a tcp or udp connection to a remote host or local socket */
-int my_swift_fwd_net_connect(const char *host_name, int port, int *sd, char* proto)
-{
-	struct sockaddr_in servaddr;
-	struct protoent *ptrp;
-	int result;
-
-	bzero((char *)&servaddr,sizeof(servaddr));
-	servaddr.sin_family=AF_INET;
-	servaddr.sin_port=htons(port);
-	inet_pton(AF_INET, host_name, &servaddr.sin_addr);
-
-	/* map transport protocol name to protocol number */
-	if(((ptrp=getprotobyname(proto)))==NULL){
-		if(DEBUG)
-			printf("Cannot map \"%s\" to protocol number\n",proto);
-		return 3;
-	}
-
-	/* create a socket */
-	*sd=socket(PF_INET,(!strcmp(proto,"udp"))?SOCK_DGRAM:SOCK_STREAM,ptrp->p_proto);
-	if(*sd<0){
-		close(*sd);
-		if(DEBUG)
-			printf("Socket creation failed\n");
-		return 3;
-	}
-	/* open a connection */
-	result=connect(*sd,(struct sockaddr *)&servaddr,sizeof(servaddr));
-	if(result<0){
-		close(*sd);
-		switch(errno){
-			case ECONNREFUSED:
-				if(DEBUG)
-					printf("Connection refused by host\n");
-				break;
-			case ETIMEDOUT:
-				if(DEBUG)
-					printf("Timeout while attempting connection\n");
-				break;
-			case ENETUNREACH:
-				if(DEBUG)
-					printf("Network is unreachable\n");
-				break;
-			default:
-				if(DEBUG)
-					printf("Connection refused or timed out\n");
-		}
-
-		return 2;
-	}
-	return 0;
-}
-ssize_t mywrite_swift_fwd(int fd, void *buf, size_t len)
-{
-	return send(fd, buf, len, 0);
-}
-
-ssize_t myread_swift_fwd(int fd, void *buf, size_t len)
-{
-	return recv(fd, buf, len, 0);
-}
-
-/* get value from counter */
-int read_swift_fwd_value(char *buf,
-		const char *key,
-		unsigned long long *ret)
-{
-	int k=0;
-	char *tmp;
-	/* is str match the keywords? */
-	if ((tmp = strstr(buf, key)) != NULL) {
-		/* compute the offset */
-		k = strcspn(tmp, EQUAL);
-		sscanf(tmp + k + 1, "%lld", ret);
-		return 1;
-	} else return 0;
-}
-int parse_swift_fwd_info(char *buf)
-{
-	char *line;
-	line = strtok(buf, "\n");
-	while(line != NULL){
-		read_swift_fwd_value(line, SWIFT_FWD[0], &stats.requests);
-		read_swift_fwd_value(line, SWIFT_FWD[1], &stats.errors);
-		read_swift_fwd_value(line, SWIFT_FWD[2], &stats.bytes_in);
-		read_swift_fwd_value(line, SWIFT_FWD[3], &stats.svc_time);
-		line = strtok(NULL, "\n");
-	}
-	return 0;
-}
-
-void set_swift_fwd_record(struct module *mod, double st_array[],
-		U_64 pre_array[], U_64 cur_array[], int inter)
-{
-	int i;
-	for (i = 0; i < mod->n_col-1; i++) {
-		if (cur_array[i] >= pre_array[i]) {
-			st_array[i] = (cur_array[i] - pre_array[i]) * 1.0 / inter;
-		}else
-			st_array[i] = -1;
-	}
-	if(cur_array[i] >= pre_array[i] && st_array[0] > 0){
-		st_array[i] = (cur_array[i] - pre_array[i]) * 1.0 / st_array[0] / inter;
-	}else
-		st_array[i] = -1;
-}
-
-int read_swift_fwd_stat()
-{
-	char msg[LEN_512];
-	char buf[LEN_4096];
-	sprintf(msg,
-			"GET cache_object://localhost/counters "
-			"HTTP/1.1\r\n"
-			"Host: localhost\r\n"
-			"Accept:*/*\r\n"
-			"Connection: close\r\n\r\n");
-
-	int len, conn, bytesWritten, fsize = 0;
-
-	if(my_swift_fwd_net_connect(HOSTNAME, mgrport, &conn, "tcp") != 0){
-		close(conn);
-		return -1;
-	}
-
-	int flags;
-
-	/* set socket fd noblock */
-	if((flags = fcntl(conn, F_GETFL, 0)) < 0) {
-		close(conn);
-		return -1;
-	}
-
-	if(fcntl(conn, F_SETFL, flags & ~O_NONBLOCK) < 0) {
-		close(conn);
-		return -1;
-	}
-
-	struct timeval timeout = {10, 0};
-
-	setsockopt(conn, SOL_SOCKET, SO_SNDTIMEO, (char *)&timeout, sizeof(struct timeval));
-
-	setsockopt(conn, SOL_SOCKET, SO_RCVTIMEO, (char *)&timeout, sizeof(struct timeval));
-
-	bytesWritten = mywrite_swift_fwd(conn, msg, strlen(msg));
-	if (bytesWritten < 0) {
-		close(conn);
-		return -2;
-	} else if (bytesWritten != strlen(msg)) {
-		close(conn);
-		return -3;
-	}
-
-	while ((len = myread_swift_fwd(conn, buf, sizeof(buf))) > 0) {
-		fsize += len;
-	}
-
-	/* read error */
-	if (fsize < 100) {
-		close(conn);
-		return -1;
-	}
-
-	if (parse_swift_fwd_info(buf) < 0) {
-		close(conn);
-		return -1;
-	}
-
-	close(conn);
-	return 0;
-}
-
-void read_swift_fwd_stats(struct module *mod, char *parameter)
-{
-	int retry = 0 ,pos = 0;
-	char buf[LEN_1024];
-	memset(&stats, 0, sizeof(stats));
-	mgrport = atoi(parameter);
-	if(!mgrport){
-		mgrport = 81;
-	}
-	while(read_swift_fwd_stat() < 0 && retry < RETRY_NUM){
-		retry++;
-	}
-	pos = sprintf(buf, "%lld,%lld,%lld,%lld",
-			stats.requests,
-			stats.bytes_in,
-			stats.errors,
-			stats.svc_time
-		     );
-	buf[pos] = '\0';
-	set_mod_record(mod, buf);
-}
-
-void mod_register(struct module *mod)
-{
-	register_mod_fileds(mod, "--swift_fwd", swift_fwd_usage, swift_fwd_info, 4, read_swift_fwd_stats, set_swift_fwd_record);
-}
diff --git a/modules/mod_swift_store.c b/modules/mod_swift_store.c
deleted file mode 100644
index f36b604..0000000
--- a/modules/mod_swift_store.c
+++ /dev/null
@@ -1,269 +0,0 @@
-#include <sys/socket.h>
-#include <fcntl.h>
-#include <string.h>
-#include "tsar.h"
-
-
-#define RETRY_NUM 3
-/* swift default port should not changed */
-#define HOSTNAME "localhost"
-#define PORT 81
-#define EQUAL ":"
-#define DEBUG 1
-
-char *swift_store_usage = "    --swift_store             Swift object storage infomation";
-int mgrport = 81;
-
-/* httpstore string at swiftclient -p 81 mgr:info */
-/*
- * Mean Object Size:       40.35 KB
- * StoreEntries           : 20676021
- * on-memory objects      : 21227
- * on-disk objects        : 106168780
- * Request Memory Hit Ratios:      5min: 71.3%, 60min: 71.8%
- * Request Filesystem Hit Ratios(5min):    coss: 9.8%, tcoss: 13.8%
- *
- *
- */
-const static char *SWIFT_STORE[] = {
-	"StoreEntries",
-	"on-memory objects",
-	"on-disk objects",
-};
-
-/* struct for httpstore counters */
-struct status_swift_store {
-	unsigned long long objs;
-	unsigned long long mobj;
-	unsigned long long dobj;
-	unsigned long long size;
-	unsigned long long m_hit;
-	unsigned long long coss;
-	unsigned long long tcoss;
-} stats;
-
-/* swift register info for tsar */
-struct mod_info swift_store_info[] = {
-	{"  objs", DETAIL_BIT,  0,  STATS_NULL},
-	{"  mobj", DETAIL_BIT,  0,  STATS_NULL},
-	{"  dobj", DETAIL_BIT,  0,  STATS_NULL},
-	{"  size", DETAIL_BIT,  0,  STATS_NULL},
-	{" m_hit", DETAIL_BIT,  0,  STATS_NULL},
-	{"  coss", DETAIL_BIT,  0,  STATS_NULL},
-	{" tcoss", DETAIL_BIT,  0,  STATS_NULL}
-};
-/* opens a tcp or udp connection to a remote host or local socket */
-int my_swift_store_net_connect(const char *host_name, int port, int *sd, char* proto)
-{
-	struct sockaddr_in servaddr;
-	struct protoent *ptrp;
-	int result;
-
-	bzero((char *)&servaddr,sizeof(servaddr));
-	servaddr.sin_family=AF_INET;
-	servaddr.sin_port=htons(port);
-	inet_pton(AF_INET, host_name, &servaddr.sin_addr);
-
-	/* map transport protocol name to protocol number */
-	if(((ptrp=getprotobyname(proto)))==NULL){
-		if(DEBUG)
-			printf("Cannot map \"%s\" to protocol number\n",proto);
-		return 3;
-	}
-
-	/* create a socket */
-	*sd=socket(PF_INET,(!strcmp(proto,"udp"))?SOCK_DGRAM:SOCK_STREAM,ptrp->p_proto);
-	if(*sd<0){
-		close(*sd);
-		if(DEBUG)
-			printf("Socket creation failed\n");
-		return 3;
-	}
-	/* open a connection */
-	result=connect(*sd,(struct sockaddr *)&servaddr,sizeof(servaddr));
-	if(result<0){
-		close(*sd);
-		switch(errno){
-			case ECONNREFUSED:
-				if(DEBUG)
-					printf("Connection refused by host\n");
-				break;
-			case ETIMEDOUT:
-				if(DEBUG)
-					printf("Timeout while attempting connection\n");
-				break;
-			case ENETUNREACH:
-				if(DEBUG)
-					printf("Network is unreachable\n");
-				break;
-			default:
-				if(DEBUG)
-					printf("Connection refused or timed out\n");
-		}
-
-		return 2;
-	}
-	return 0;
-}
-ssize_t mywrite_swift_store(int fd, void *buf, size_t len)
-{
-	return send(fd, buf, len, 0);
-}
-
-ssize_t myread_swift_store(int fd, void *buf, size_t len)
-{
-	return recv(fd, buf, len, 0);
-}
-
-/* get value from counter */
-int read_swift_store_value(char *buf,
-		const char *key,
-		unsigned long long *ret)
-{
-	int k=0;
-	char *tmp;
-	/* is str match the keywords? */
-	if ((tmp = strstr(buf, key)) != NULL) {
-		/* compute the offset */
-		k = strcspn(tmp, EQUAL);
-		sscanf(tmp + k + 1, "%lld", ret);
-		return 1;
-	} else return 0;
-}
-int parse_swift_store_info(char *buf)
-{
-	char *line;
-	line = strtok(buf, "\n");
-	while(line != NULL){
-		read_swift_store_value(line, SWIFT_STORE[0], &stats.objs);
-		read_swift_store_value(line, SWIFT_STORE[1], &stats.mobj);
-		read_swift_store_value(line, SWIFT_STORE[2], &stats.dobj);
-		/*Mean Object Size:       40.35 KB */
-		if(strstr(line,"Mean Object Size:") != NULL){
-			float a;
-			sscanf(line,"        Mean Object Size:       %f KB",&a);
-			stats.size = a * 1000;
-		}
-		/*Request Memory Hit Ratios:      5min: 71.3%, 60min: 71.8% */
-		if(strstr(line,"Request Memory Hit Ratios:") != NULL){
-			float a,b;
-			sscanf(line,"        Request Memory Hit Ratios:      5min: %f%%, 60min: %f%%",&a,&b);
-			stats.m_hit = a * 1000;
-		}
-		/*Request Filesystem Hit Ratios(5min):    coss: 9.8%, tcoss: 13.8%*/
-		if(strstr(line,"Request Filesystem Hit Ratios(5min):") != NULL){
-			float a,b;
-			sscanf(line,"        Request Filesystem Hit Ratios(5min):    coss: %f%%, tcoss: %f%%",&a,&b);
-			stats.coss= a * 1000;
-			stats.tcoss = b * 1000;
-		}
-		line = strtok(NULL, "\n");
-	}
-	return 0;
-}
-
-void set_swift_store_record(struct module *mod, double st_array[],
-		U_64 pre_array[], U_64 cur_array[], int inter)
-{
-	int i;
-	for (i = 0; i < mod->n_col; i++) {
-		st_array[i] = cur_array[i];
-		if(i >= 4)
-			st_array[i] /= 1000;
-	}
-}
-
-int read_swift_store_stat()
-{
-	char msg[LEN_512];
-	char buf[LEN_4096];
-	sprintf(msg,
-			"GET cache_object://localhost/info "
-			"HTTP/1.1\r\n"
-			"Host: localhost\r\n"
-			"Accept:*/*\r\n"
-			"Connection: close\r\n\r\n");
-
-	int len, conn, bytesWritten, fsize = 0;
-
-	if(my_swift_store_net_connect(HOSTNAME, mgrport, &conn, "tcp") != 0){
-		close(conn);
-		return -1;
-	}
-
-	int flags;
-
-	/* set socket fd noblock */
-	if((flags = fcntl(conn, F_GETFL, 0)) < 0) {
-		close(conn);
-		return -1;
-	}
-
-	if(fcntl(conn, F_SETFL, flags & ~O_NONBLOCK) < 0) {
-		close(conn);
-		return -1;
-	}
-
-	struct timeval timeout = {10, 0};
-
-	setsockopt(conn, SOL_SOCKET, SO_SNDTIMEO, (char *)&timeout, sizeof(struct timeval));
-
-	setsockopt(conn, SOL_SOCKET, SO_RCVTIMEO, (char *)&timeout, sizeof(struct timeval));
-
-	bytesWritten = mywrite_swift_store(conn, msg, strlen(msg));
-	if (bytesWritten < 0) {
-		close(conn);
-		return -2;
-	} else if (bytesWritten != strlen(msg)) {
-		close(conn);
-		return -3;
-	}
-
-	while ((len = myread_swift_store(conn, buf, sizeof(buf))) > 0) {
-		fsize += len;
-	}
-
-	/* read error */
-	if (fsize < 100) {
-		close(conn);
-		return -1;
-	}
-
-	if (parse_swift_store_info(buf) < 0) {
-		close(conn);
-		return -1;
-	}
-
-	close(conn);
-	return 0;
-}
-
-void read_swift_store_stats(struct module *mod, char *parameter)
-{
-	int retry = 0 ,pos = 0;
-	char buf[LEN_1024];
-	memset(&stats, 0, sizeof(stats));
-	mgrport = atoi(parameter);
-	if(!mgrport){
-		mgrport = 81;
-	}
-	while(read_swift_store_stat() < 0 && retry < RETRY_NUM){
-		retry++;
-	}
-	pos = sprintf(buf, "%lld,%lld,%lld,%lld,%lld,%lld,%lld",
-			stats.objs,
-			stats.mobj,
-			stats.dobj,
-			stats.size,
-			stats.m_hit,
-			stats.coss,
-			stats.tcoss
-		     );
-	buf[pos] = '\0';
-	set_mod_record(mod, buf);
-}
-
-void mod_register(struct module *mod)
-{
-	register_mod_fileds(mod, "--swift_store", swift_store_usage, swift_store_info, 7, read_swift_store_stats, set_swift_store_record);
-}
diff --git a/modules/mod_swift_tcmalloc.c b/modules/mod_swift_tcmalloc.c
deleted file mode 100644
index e494c5e..0000000
--- a/modules/mod_swift_tcmalloc.c
+++ /dev/null
@@ -1,320 +0,0 @@
-#include <sys/socket.h>
-#include <fcntl.h>
-#include "tsar.h"
-
-
-#define RETRY_NUM 3
-/* swift default port should not changed */
-#define HOSTNAME "localhost"
-#define PORT 81
-#define EQUAL "="
-#define DEBUG 0
-
-char *swift_tcmalloc_usage = "    --swift_tcmalloc             Swift tcmalloc";
-int mgrport = 81;
-
-/* httpcode string at swiftclient -p 81 mgr:mem_stats */
-/*
-   ------------------------------------------------
-MALLOC:        4916632 (    4.7 MB) Bytes in use by application
-MALLOC: +      4399104 (    4.2 MB) Bytes in page heap freelist
-MALLOC: +       105992 (    0.1 MB) Bytes in central cache freelist
-MALLOC: +            0 (    0.0 MB) Bytes in transfer cache freelist
-MALLOC: +        15456 (    0.0 MB) Bytes in thread cache freelists
-MALLOC: +       655360 (    0.6 MB) Bytes in malloc metadata
-MALLOC:   ------------
-MALLOC: =     10092544 (    9.6 MB) Actual memory used (physical + swap)
-MALLOC: +            0 (    0.0 MB) Bytes released to OS (aka unmapped)
-MALLOC:   ------------
-MALLOC: =     10092544 (    9.6 MB) Virtual address space used
-MALLOC:
-MALLOC:             53              Spans in use
-MALLOC:              5              Thread heaps in use
-MALLOC:           4096              Tcmalloc page size
-------------------------------------------------
- */
-
-#define DATA_COUNT (sizeof(SWIFT_TCMALLOC)/sizeof(SWIFT_TCMALLOC[0]))
-const static char *SWIFT_TCMALLOC[] = {
-	"Bytes in use by application",
-	"Bytes in page heap freelist",
-	"Bytes in central cache freelist",
-	"Bytes in transfer cache freelist",
-	"Bytes in thread cache freelists",
-	"Bytes in malloc metadata",
-	"Actual memory used",
-	"Bytes released to OS",
-	"Virtual address space used",
-	"Spans in use",
-	"Thread heaps in use",
-	"Tcmalloc page size",
-};
-
-/* struct for httpcode counters */
-struct status_swift_tcmalloc {
-	unsigned long long uba;
-	unsigned long long phf;
-	unsigned long long ccf;
-	unsigned long long trcf;
-	unsigned long long thcf;
-	unsigned long long mm;
-	unsigned long long amu;
-	unsigned long long brto;
-	unsigned long long vasu;
-	unsigned long long siu;
-	unsigned long long thiu;
-	unsigned long long tps;
-} stats;
-
-/* swift register info for tsar */
-struct mod_info swift_tcmalloc_info[] = {
-	{"   uba", DETAIL_BIT,  0,  STATS_NULL},
-	{"   phf", DETAIL_BIT,  0,  STATS_NULL},
-	{"   ccf", DETAIL_BIT,  0,  STATS_NULL},
-	{"  trcf", DETAIL_BIT,  0,  STATS_NULL},
-	{"  thcf", DETAIL_BIT,  0,  STATS_NULL},
-	{"    mm", DETAIL_BIT,  0,  STATS_NULL},
-	{"   amu", DETAIL_BIT,  0,  STATS_NULL},
-	{"  brto", DETAIL_BIT,  0,  STATS_NULL},
-	{"  vasu", DETAIL_BIT,  0,  STATS_NULL},
-	{"   siu", DETAIL_BIT,  0,  STATS_NULL},
-	{"  thiu", DETAIL_BIT,  0,  STATS_NULL},
-	{"   tps", DETAIL_BIT,  0,  STATS_NULL},
-};
-/* opens a tcp or udp connection to a remote host or local socket */
-int my_swift_tcmalloc_net_connect(const char *host_name, int port, int *sd, char *proto)
-{
-	struct sockaddr_in servaddr;
-	struct protoent *ptrp;
-	int result;
-
-	bzero((char *)&servaddr, sizeof(servaddr));
-	servaddr.sin_family = AF_INET;
-	servaddr.sin_port = htons(port);
-	inet_pton(AF_INET, host_name, &servaddr.sin_addr);
-
-	/* map transport protocol name to protocol number */
-	if(((ptrp = getprotobyname(proto))) == NULL) {
-		if(DEBUG)
-			printf("Cannot map \"%s\" to protocol number\n", proto);
-
-		return 3;
-	}
-
-	/* create a socket */
-	*sd = socket(PF_INET, (!strcmp(proto, "udp")) ? SOCK_DGRAM : SOCK_STREAM, ptrp->p_proto);
-
-	if(*sd < 0) {
-		close(*sd);
-
-		if(DEBUG)
-			printf("Socket creation failed\n");
-
-		return 3;
-	}
-
-	/* open a connection */
-	result = connect(*sd, (struct sockaddr *)&servaddr, sizeof(servaddr));
-
-	if(result < 0) {
-		close(*sd);
-
-		switch(errno) {
-			case ECONNREFUSED:
-				if(DEBUG)
-					printf("Connection refused by host\n");
-
-				break;
-
-			case ETIMEDOUT:
-				if(DEBUG)
-					printf("Timeout while attempting connection\n");
-
-				break;
-
-			case ENETUNREACH:
-				if(DEBUG)
-					printf("Network is unreachable\n");
-
-				break;
-
-			default:
-				if(DEBUG)
-					printf("Connection refused or timed out\n");
-		}
-
-		return 2;
-	}
-
-	return 0;
-}
-ssize_t mywrite_swift_tcmalloc(int fd, void *buf, size_t len)
-{
-	return send(fd, buf, len, 0);
-}
-
-ssize_t myread_swift_tcmalloc(int fd, void *buf, size_t len)
-{
-	return recv(fd, buf, len, 0);
-}
-
-/* get value from counter */
-int read_swift_tcmalloc_value(char *buf,
-		const char *key,
-		unsigned long long *ret)
-{
-	char *p;
-
-	/* is str match the keywords? */
-	if ((p = strstr(buf, key)) != NULL) {
-		p = buf;
-
-		/* compute the offset */
-		if (strncmp(buf, "MALLOC:  ", sizeof("MALLOC:  ") - 1) == 0) {
-			p += sizeof("MALLOC:  ") - 1;
-		} else if (strncmp(buf, "MALLOC: +", sizeof("MALLOC: +") - 1) == 0) {
-			p += sizeof("MALLOC: +") - 1;
-		} else if (strncmp(buf, "MALLOC: =", sizeof("MALLOC: =") - 1) == 0) {
-			p += sizeof("MALLOC: =") - 1;
-		}
-
-		while(isspace(*p)) p ++;
-
-		//fprintf(stderr, "read_swift_tcmalloc_value: key: %s, buf: %s, p: %s\n", key, buf, p);
-
-		if (isalnum(*p) == 0) return 0;
-
-		*ret = atoll(p);
-
-		return 1;
-	} else return 0;
-}
-int parse_swift_tcmalloc_info(char *buf)
-{
-	char *line;
-	int  i;
-	line = strtok(buf, "\n");
-
-	while(line != NULL) {
-		for (i = 0; i < DATA_COUNT; i ++) {
-			read_swift_tcmalloc_value(line, SWIFT_TCMALLOC[i],
-					(unsigned long long *)((char *)&stats + i * sizeof(unsigned long long)));
-		};
-
-		line = strtok(NULL, "\n");
-	}
-
-	return 0;
-}
-
-void set_swift_tcmalloc_record(struct module *mod, double st_array[],
-		U_64 pre_array[], U_64 cur_array[], int inter)
-{
-	int i;
-
-	for (i = 0; i < mod->n_col; i++) {
-		st_array[i] = cur_array[i];
-	}
-}
-
-int read_swift_tcmalloc_stat()
-{
-	char msg[LEN_512];
-	char buf[LEN_4096];
-	sprintf(msg,
-			"GET cache_object://localhost/mem_stats "
-			"HTTP/1.1\r\n"
-			"Host: localhost\r\n"
-			"Accept:*/*\r\n"
-			"Connection: close\r\n\r\n");
-
-	int len, conn, bytesWritten, fsize = 0;
-
-	if(my_swift_tcmalloc_net_connect(HOSTNAME, mgrport, &conn, "tcp") != 0) {
-		close(conn);
-		return -1;
-	}
-
-	int flags;
-
-	/* set socket fd noblock */
-	if((flags = fcntl(conn, F_GETFL, 0)) < 0) {
-		close(conn);
-		return -1;
-	}
-
-	if(fcntl(conn, F_SETFL, flags & ~O_NONBLOCK) < 0) {
-		close(conn);
-		return -1;
-	}
-
-	struct timeval timeout = {10, 0};
-
-	setsockopt(conn, SOL_SOCKET, SO_SNDTIMEO, (char *)&timeout, sizeof(struct timeval));
-
-	setsockopt(conn, SOL_SOCKET, SO_RCVTIMEO, (char *)&timeout, sizeof(struct timeval));
-
-	bytesWritten = mywrite_swift_tcmalloc(conn, msg, strlen(msg));
-
-	if (bytesWritten < 0) {
-		close(conn);
-		return -2;
-	} else if (bytesWritten != strlen(msg)) {
-		close(conn);
-		return -3;
-	}
-
-	while ((len = myread_swift_tcmalloc(conn, buf, sizeof(buf))) > 0) {
-		fsize += len;
-	}
-
-	/* read error */
-	if (fsize < 0) {
-		close(conn);
-		return -1;
-	}
-
-	if (parse_swift_tcmalloc_info(buf) < 0) {
-		close(conn);
-		return -1;
-	}
-
-	close(conn);
-	return 0;
-}
-
-void read_swift_tcmalloc_stats(struct module *mod, char *parameter)
-{
-	int retry = 0 , pos = 0;
-	char buf[LEN_1024];
-	memset(&stats, 0, sizeof(stats));
-	mgrport = atoi(parameter);
-	if(!mgrport){
-		mgrport = 81;
-	}
-	while(read_swift_tcmalloc_stat() < 0 && retry < RETRY_NUM) {
-		retry++;
-	}
-
-	pos = sprintf(buf, "%lld,%lld,%lld,%lld,%lld,%lld,%lld,%lld,%lld,%lld,%lld,%lld",
-			stats.uba,
-			stats.phf,
-			stats.ccf,
-			stats.trcf,
-			stats.thcf,
-			stats.mm,
-			stats.amu,
-			stats.brto,
-			stats.vasu,
-			stats.siu,
-			stats.thiu,
-			stats.tps
-		     );
-	buf[pos] = '\0';
-	set_mod_record(mod, buf);
-}
-
-void mod_register(struct module *mod)
-{
-	register_mod_fileds(mod, "--swift_tcmalloc", swift_tcmalloc_usage, swift_tcmalloc_info, DATA_COUNT, read_swift_tcmalloc_stats, set_swift_tcmalloc_record);
-}
diff --git a/modules/mod_tcp.c b/modules/mod_tcp.c
index ec0a3d4..0ea61d4 100644
--- a/modules/mod_tcp.c
+++ b/modules/mod_tcp.c
@@ -6,95 +6,108 @@ char *tcp_usage =
 
 /* Structure for TCP statistics */
 struct stats_tcp {
-	unsigned long long ActiveOpens;
-	unsigned long long PassiveOpens;
-	unsigned long long InSegs;
-	unsigned long long OutSegs;
-	unsigned long long AttemptFails;
-	unsigned long long EstabResets;
-	unsigned long long RetransSegs;
-	unsigned long long InErrs;
-	unsigned long long OutRsts;
+    unsigned long long ActiveOpens;
+    unsigned long long PassiveOpens;
+    unsigned long long InSegs;
+    unsigned long long OutSegs;
+    unsigned long long AttemptFails;
+    unsigned long long EstabResets;
+    unsigned long long CurrEstab;
+    unsigned long long RetransSegs;
+    unsigned long long InErrs;
+    unsigned long long OutRsts;
 };
 
 #define STATS_TCP_SIZE      (sizeof(struct stats_tcp))
 
-void read_tcp_stats(struct module *mod)
+void
+read_tcp_stats(struct module *mod)
 {
-	FILE *fp;
-	char line[LEN_1024];
-	char buf[LEN_1024];
-	memset(buf, 0, LEN_1024);
-	int sw = FALSE;
-	struct stats_tcp st_tcp;
-	memset(&st_tcp, 0, sizeof(struct stats_tcp));
-	if ((fp = fopen(NET_SNMP, "r")) == NULL) {
-		return;
-	}
+    int               sw = FALSE;
+    FILE             *fp;
+    char              line[LEN_1024];
+    char              buf[LEN_1024];
+    struct stats_tcp  st_tcp;
 
-	while (fgets(line, LEN_1024, fp) != NULL) {
+    memset(buf, 0, LEN_1024);
+    memset(&st_tcp, 0, sizeof(struct stats_tcp));
+    if ((fp = fopen(NET_SNMP, "r")) == NULL) {
+        return;
+    }
 
-		if (!strncmp(line, "Tcp:", 4)) {
-			if (sw) {
-				sscanf(line + 4, "%*u %*u %*u %*d %llu %llu "
-						"%llu %llu %*u %llu %llu %llu %llu %llu",
-						&st_tcp.ActiveOpens,
-						&st_tcp.PassiveOpens,
-						&st_tcp.AttemptFails,
-						&st_tcp.EstabResets,
-						&st_tcp.InSegs,
-						&st_tcp.OutSegs,
-						&st_tcp.RetransSegs,
-						&st_tcp.InErrs,
-						&st_tcp.OutRsts);
-				break;
-			} else {
-				sw = TRUE;
-			}
-		}
-	}
+    while (fgets(line, LEN_1024, fp) != NULL) {
+        if (!strncmp(line, "Tcp:", 4)) {
+            if (sw) {
+                sscanf(line + 4, "%*u %*u %*u %*d %llu %llu "
+                        "%llu %llu %llu %llu %llu %llu %llu %llu",
+                        &st_tcp.ActiveOpens,
+                        &st_tcp.PassiveOpens,
+                        &st_tcp.AttemptFails,
+                        &st_tcp.EstabResets,
+                        &st_tcp.CurrEstab,
+                        &st_tcp.InSegs,
+                        &st_tcp.OutSegs,
+                        &st_tcp.RetransSegs,
+                        &st_tcp.InErrs,
+                        &st_tcp.OutRsts);
+                break;
 
-	fclose(fp);
+            } else {
+                sw = TRUE;
+            }
+        }
+    }
 
-	int pos = sprintf(buf, "%lld,%lld,%lld,%lld,%lld",
-			st_tcp.ActiveOpens,
-			st_tcp.PassiveOpens,
-			st_tcp.InSegs,
-			st_tcp.OutSegs,
-			st_tcp.RetransSegs);
-	buf[pos] = '\0';
-	set_mod_record(mod, buf);
+    fclose(fp);
+
+    int pos = sprintf(buf, "%lld,%lld,%lld,%lld,%lld,%lld,%lld,%lld",
+            st_tcp.ActiveOpens,
+            st_tcp.PassiveOpens,
+            st_tcp.InSegs,
+            st_tcp.OutSegs,
+            st_tcp.EstabResets,
+            st_tcp.AttemptFails,
+            st_tcp.CurrEstab,
+            st_tcp.RetransSegs);
+
+    buf[pos] = '\0';
+    set_mod_record(mod, buf);
 }
 
-static void set_tcp_record(struct module *mod, double st_array[],
-		U_64 pre_array[], U_64 cur_array[], int inter)
+static void
+set_tcp_record(struct module *mod, double st_array[],
+    U_64 pre_array[], U_64 cur_array[], int inter)
 {
-	int i;
-	for (i = 0; i < 4; i++) {
-		if(cur_array[i] >= pre_array[i])
-			st_array[i] = (cur_array[i] - pre_array[i]) * 1.0 / inter;
-		//	else
-		//		st_array[i] = 0;
-	}
-	if((cur_array[4] >= pre_array[4]) && (cur_array[3] > pre_array[3]))
-		st_array[4] = (cur_array[4]- pre_array[4]) * 100.0 / (cur_array[3]- pre_array[3]);
-	if(st_array[4] > 100.0)
-		st_array[4] = 100.0;
-	//else
-	//	st_array[4] = 0;
+    int i;
+    for (i = 0; i < 6; i++) {
+        if (cur_array[i] >= pre_array[i]) {
+            st_array[i] = (cur_array[i] - pre_array[i]) * 1.0 / inter;
+        }
+    }
+    /* 6 is for st_tcp.CurrEstab */
+    st_array[6] = cur_array[6];
+    /* as for st_tcp.RetransSegs,  we calculate the retransfer radio.  Retrans/outSegs */
+    if ((cur_array[7] >= pre_array[7]) && (cur_array[3] > pre_array[3])) {
+        st_array[7] = (cur_array[7]- pre_array[7]) * 100.0 / (cur_array[3]- pre_array[3]);
+    }
+    if (st_array[7] > 100.0) {
+        st_array[7] = 100.0;
+    }
 }
 
-
 static struct mod_info tcp_info[] = {
-	{"active", DETAIL_BIT,  0,  STATS_SUB_INTER},
-	{"pasive", DETAIL_BIT,  0,  STATS_SUB_INTER},
-	{"  iseg", DETAIL_BIT,  0,  STATS_SUB_INTER},
-	{"outseg", DETAIL_BIT,  0,  STATS_SUB_INTER},
-	{"retran", SUMMARY_BIT,  0,  STATS_SUB_INTER}
+    {"active", DETAIL_BIT,  0,  STATS_SUB_INTER},
+    {"pasive", DETAIL_BIT,  0,  STATS_SUB_INTER},
+    {"  iseg", DETAIL_BIT,  0,  STATS_SUB_INTER},
+    {"outseg", DETAIL_BIT,  0,  STATS_SUB_INTER},
+    {"EstReset", DETAIL_BIT,  0,  STATS_SUB_INTER},
+    {"AtmpFail", DETAIL_BIT,  0,  STATS_SUB_INTER},
+    {"CurrEstab", DETAIL_BIT,  0,  STATS_SUB_INTER},
+    {"retran", SUMMARY_BIT,  0,  STATS_SUB_INTER}
 };
 
-void mod_register(struct module *mod)
+void
+mod_register(struct module *mod)
 {
-	register_mod_fileds(mod, "--tcp", tcp_usage, tcp_info, 5, read_tcp_stats, set_tcp_record);
+    register_mod_fields(mod, "--tcp", tcp_usage, tcp_info, 8, read_tcp_stats, set_tcp_record);
 }
-
diff --git a/modules/mod_tcpx.c b/modules/mod_tcpx.c
index 064b159..f8b7c5c 100644
--- a/modules/mod_tcpx.c
+++ b/modules/mod_tcpx.c
@@ -3,130 +3,135 @@
 char * tcpx_usage="    --tcpx              TCP connection data";
 
 struct stats_tcpx{
-	unsigned long long tcprecvq;
-	unsigned long long tcpsendq;
-	unsigned long long tcpest;
-	unsigned long long tcptimewait;
-	unsigned long long tcpfinwait1;
-	unsigned long long tcpfinwait2;
-	unsigned long long tcplistenq;					// set to zero than never change
-	unsigned long long tcplistenincq;				// set to zero than ....
-	unsigned long long tcplistenover;
-	unsigned long long tcpnconnest;
-	unsigned long long tcpnconndrop;					//set to zero than ...
-	unsigned long long tcpembdrop;
-	unsigned long long tcprexmitdrop;
-	unsigned long long tcppersistdrop;				// set to zero than ..,
-	unsigned long long tcpkadrop;					//set to zero than ...
+    unsigned long long tcprecvq;
+    unsigned long long tcpsendq;
+    unsigned long long tcpest;
+    unsigned long long tcptimewait;
+    unsigned long long tcpfinwait1;
+    unsigned long long tcpfinwait2;
+    unsigned long long tcplistenq;
+    unsigned long long tcplistenincq;
+    unsigned long long tcplistenover;
+    unsigned long long tcpnconnest;
+    unsigned long long tcpnconndrop;
+    unsigned long long tcpembdrop;
+    unsigned long long tcprexmitdrop;
+    unsigned long long tcppersistdrop;
+    unsigned long long tcpkadrop;
 };
 
-static void read_stat_tcpx(struct module *mod)
+static void
+read_stat_tcpx(struct module *mod)
 {
-	FILE *fp_tcp;
-	FILE *fp_snmp;
-	FILE *fp_netstat;
-	struct stats_tcpx st_tcpx;
-	char buf[LEN_4096], line[LEN_4096];
-	int sw;
-	memset(buf, 0, LEN_4096);
-	memset(&st_tcpx, 0, sizeof(struct stats_tcpx));
+    int                sw;
+    FILE              *fp_tcp;
+    FILE              *fp_snmp;
+    FILE              *fp_netstat;
+    char               buf[LEN_4096], line[LEN_4096];
+    struct stats_tcpx  st_tcpx;
 
-	fp_tcp = fopen(TCP, "r");
-	if(fp_tcp == NULL){
-		return;
-	}
+    memset(buf, 0, LEN_4096);
+    memset(&st_tcpx, 0, sizeof(struct stats_tcpx));
 
-	fp_snmp = fopen(NET_SNMP, "r");
-	if(fp_snmp == NULL){
-		return;
-	}
-	fp_netstat = fopen(NETSTAT, "r");
-	if(fp_netstat == NULL){
-		return;
-	}	
-	st_tcpx.tcplistenq = 0;
-	st_tcpx.tcplistenincq = 0;
+    fp_tcp = fopen(TCP, "r");
+    if (fp_tcp == NULL) {
+        return;
+    }
 
-	sw = 0;
-	while(fgets(line, LEN_4096, fp_netstat) !=NULL) {
-		if(!strncmp(line, "TcpExt:", 7)) {
-			if (!sw) {sw = 1; continue;}
-			sscanf(line + 7, 
-					"%*u %*u %*u %*u %*u %*u %*u %*u %*u "
-					"%*u %*u %*u %*u %*u %*u %*u %*u %*u "
-					"%*u %llu %*u %*u %*u %*u %*u %*u %*u "
-					"%*u %*u %*u %*u %*u %*u %*u %*u %*u "
-					"%*u %*u %*u %*u %*u %*u %*u %*u %*u "
-					"%*u %*u %*u %*u %*u %*u %*u %*u %*u "
-					"%*u %*u %*u %llu %*u %*u %*u %llu",
-					&st_tcpx.tcplistenover,
-					&st_tcpx.tcpembdrop,
-					&st_tcpx.tcprexmitdrop);
-			break;
-		}
-	}
-	sw = 0;
-	unsigned long activeopen, passiveopen;
-	activeopen = 0;
-	passiveopen = 0;
-	while(fgets(line, LEN_4096, fp_snmp) !=NULL) {
-		if(!strncmp(line, "Tcp:", 4)) {
-			if (!sw) {sw = 1; continue;}
-			sscanf(line + 4, "%*u %*u %*u %*d %lu %lu",
-					&activeopen,&passiveopen);
-			break;
-		}
-	}
+    fp_snmp = fopen(NET_SNMP, "r");
+    if (fp_snmp == NULL) {
+        fclose(fp_tcp);
+        return;
+    }
+    fp_netstat = fopen(NETSTAT, "r");
+    if (fp_netstat == NULL) {
+        fclose(fp_snmp);
+        fclose(fp_tcp);
+        return;
+    }
+    st_tcpx.tcplistenq = 0;
+    st_tcpx.tcplistenincq = 0;
 
-	st_tcpx.tcpnconnest = activeopen + passiveopen;
-	st_tcpx.tcpnconndrop = 0;
-	st_tcpx.tcppersistdrop = 0;
-	st_tcpx.tcpkadrop = 0;
+    sw = 0;
+    while (fgets(line, LEN_4096, fp_netstat) !=NULL) {
+        if (!strncmp(line, "TcpExt:", 7)) {
+            if (!sw) {sw = 1; continue;}
+            sscanf(line + 7,
+                    "%*u %*u %*u %*u %*u %*u %*u %*u %*u "
+                    "%*u %*u %*u %*u %*u %*u %*u %*u %*u "
+                    "%*u %llu %*u %*u %*u %*u %*u %*u %*u "
+                    "%*u %*u %*u %*u %*u %*u %*u %*u %*u "
+                    "%*u %*u %*u %*u %*u %*u %*u %*u %*u "
+                    "%*u %*u %*u %*u %*u %*u %*u %*u %*u "
+                    "%*u %*u %*u %llu %*u %*u %*u %llu",
+                    &st_tcpx.tcplistenover,
+                    &st_tcpx.tcpembdrop,
+                    &st_tcpx.tcprexmitdrop);
+            break;
+        }
+    }
+    sw = 0;
+    unsigned long activeopen, passiveopen;
+    activeopen = 0;
+    passiveopen = 0;
+    while (fgets(line, LEN_4096, fp_snmp) !=NULL) {
+        if (!strncmp(line, "Tcp:", 4)) {
+            if (!sw) {sw = 1; continue;}
+            sscanf(line + 4, "%*u %*u %*u %*d %lu %lu",
+                    &activeopen, &passiveopen);
+            break;
+        }
+    }
 
-	int pos = sprintf(buf, 
-			"%llu,%llu,%llu,%llu,%llu,%llu,%llu,%llu,"
-			"%llu,%llu,%llu,%llu,%llu,%llu,%llu",
-			st_tcpx.tcprecvq,
-			st_tcpx.tcpsendq,
-			st_tcpx.tcpest,
-			st_tcpx.tcptimewait,
-			st_tcpx.tcpfinwait1,
-			st_tcpx.tcpfinwait2,
-			st_tcpx.tcplistenq,
-			st_tcpx.tcplistenincq,
-			st_tcpx.tcplistenover,
-			st_tcpx.tcpnconnest,
-			st_tcpx.tcpnconndrop,
-			st_tcpx.tcpembdrop,
-			st_tcpx.tcprexmitdrop,
-			st_tcpx.tcppersistdrop,
-			st_tcpx.tcpkadrop);
-	buf[pos] = '\0';
-	set_mod_record(mod, buf);
-	fclose(fp_tcp);
-	fclose(fp_snmp);
-	fclose(fp_netstat);
+    st_tcpx.tcpnconnest = activeopen + passiveopen;
+    st_tcpx.tcpnconndrop = 0;
+    st_tcpx.tcppersistdrop = 0;
+    st_tcpx.tcpkadrop = 0;
+
+    sprintf(buf,
+            "%llu,%llu,%llu,%llu,%llu,%llu,%llu,%llu,"
+            "%llu,%llu,%llu,%llu,%llu,%llu,%llu",
+            st_tcpx.tcprecvq,
+            st_tcpx.tcpsendq,
+            st_tcpx.tcpest,
+            st_tcpx.tcptimewait,
+            st_tcpx.tcpfinwait1,
+            st_tcpx.tcpfinwait2,
+            st_tcpx.tcplistenq,
+            st_tcpx.tcplistenincq,
+            st_tcpx.tcplistenover,
+            st_tcpx.tcpnconnest,
+            st_tcpx.tcpnconndrop,
+            st_tcpx.tcpembdrop,
+            st_tcpx.tcprexmitdrop,
+            st_tcpx.tcppersistdrop,
+            st_tcpx.tcpkadrop);
+    set_mod_record(mod, buf);
+    fclose(fp_tcp);
+    fclose(fp_snmp);
+    fclose(fp_netstat);
 }
+
 static struct mod_info tcpx_info[]={
-	{" recvq", DETAIL_BIT,  0,  STATS_NULL},
-	{" sendq", DETAIL_BIT,  0,  STATS_NULL},
-	{"   est", DETAIL_BIT,  0,  STATS_NULL},
-	{" twait", DETAIL_BIT,  0,  STATS_NULL},
-	{"fwait1", DETAIL_BIT,  0,  STATS_NULL},
-	{"fwait2", DETAIL_BIT,  0,  STATS_NULL},
-	{"  lisq", DETAIL_BIT,  0,  STATS_NULL},
-	{"lising", DETAIL_BIT,  0,  STATS_NULL},
-	{"lisove", DETAIL_BIT,  0,  STATS_SUB_INTER},
-	{" cnest", DETAIL_BIT,  0,  STATS_SUB_INTER},
-	{" ndrop", DETAIL_BIT,  0,  STATS_SUB_INTER},
-	{" edrop", DETAIL_BIT,  0,  STATS_SUB_INTER},
-	{" rdrop", DETAIL_BIT,  0,  STATS_SUB_INTER},
-	{" pdrop", DETAIL_BIT,  0,  STATS_SUB_INTER},
-	{" kdrop", DETAIL_BIT,  0,  STATS_SUB_INTER},
+    {" recvq", DETAIL_BIT,  0,  STATS_NULL},
+    {" sendq", DETAIL_BIT,  0,  STATS_NULL},
+    {"   est", DETAIL_BIT,  0,  STATS_NULL},
+    {" twait", DETAIL_BIT,  0,  STATS_NULL},
+    {"fwait1", DETAIL_BIT,  0,  STATS_NULL},
+    {"fwait2", DETAIL_BIT,  0,  STATS_NULL},
+    {"  lisq", DETAIL_BIT,  0,  STATS_NULL},
+    {"lising", DETAIL_BIT,  0,  STATS_NULL},
+    {"lisove", DETAIL_BIT,  0,  STATS_SUB_INTER},
+    {" cnest", DETAIL_BIT,  0,  STATS_SUB_INTER},
+    {" ndrop", DETAIL_BIT,  0,  STATS_SUB_INTER},
+    {" edrop", DETAIL_BIT,  0,  STATS_SUB_INTER},
+    {" rdrop", DETAIL_BIT,  0,  STATS_SUB_INTER},
+    {" pdrop", DETAIL_BIT,  0,  STATS_SUB_INTER},
+    {" kdrop", DETAIL_BIT,  0,  STATS_SUB_INTER},
 };
 
-void mod_register(struct module *mod)
+void
+mod_register(struct module *mod)
 {
-	register_mod_fileds(mod, "--tcpx", tcpx_usage, tcpx_info, 15, read_stat_tcpx, NULL);
+    register_mod_fields(mod, "--tcpx", tcpx_usage, tcpx_info, 15, read_stat_tcpx, NULL);
 }
-
diff --git a/modules/mod_tmd.c b/modules/mod_tmd.c
deleted file mode 100644
index a3d95f2..0000000
--- a/modules/mod_tmd.c
+++ /dev/null
@@ -1,162 +0,0 @@
-#include <sys/socket.h>
-#include <sys/un.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#include <fcntl.h>
-#include "tsar.h"
-
-struct stats_tmd {
-	unsigned long long nprocess;    /* tmd process requests */
-	unsigned long long ncheckcode;  /* return checkcode requests */
-	unsigned long long nwait;       /* return wait requests */
-	unsigned long long ndeny;       /* return deny requests */
-};
-
-struct hostinfo {
-	char *host;
-	int port;
-	char *server_name;
-	char *uri;
-};
-
-static char *tmd_usage = "    --tmd               tmd statistics";
-
-static struct mod_info tmd_info[] = {
-	{"proces", DETAIL_BIT,  0,  STATS_NULL},
-	{" check", DETAIL_BIT,  0,  STATS_NULL},
-	{"  wait", DETAIL_BIT,  0,  STATS_NULL},
-	{"  deny", DETAIL_BIT,  0,  STATS_NULL}
-};
-
-
-static void set_tmd_record(struct module *mod, double st_array[],
-		U_64 pre_array[], U_64 cur_array[], int inter)
-{
-	int i;
-	for (i = 0; i < 4; i++) {
-
-		if (cur_array[i] >= pre_array[i]) {
-			st_array[i] = (cur_array[i] - pre_array[i]) * 1.0 / inter;
-
-		} else {
-
-			st_array[i] = -1;
-		}
-
-	}
-}
-
-
-static void init_tmd_host_info(struct hostinfo *p)
-{
-	char *port;
-
-	p->host = getenv("TMD_TSAR_HOST");
-	p->host = p->host ? p->host : "127.0.0.1";
-
-	port = getenv("TMD_TSAR_PORT");
-	p->port = port ? atoi(port) : 80;
-
-	p->uri = getenv("TMD_TSAR_URI");
-	p->uri = p->uri ? p->uri : "/tmd_status";
-
-	p->server_name = getenv("TMD_TSAR_SERVER_NAME");
-	p->server_name = p->server_name ? p->server_name : "tmd.status.taobao.com";
-}
-
-
-void read_tmd_stats(struct module *mod)
-{
-	int write_flag = 0, addr_len, domain;
-	int m, sockfd, send, pos;
-	void *addr;
-	char buf[LEN_4096], request[LEN_4096], line[LEN_4096];
-
-	struct sockaddr_in servaddr;
-	struct sockaddr_un servaddr_un;
-	FILE *stream = NULL;
-	struct hostinfo hinfo;
-	init_tmd_host_info(&hinfo);
-	struct stats_tmd st_tmd;
-	memset(&st_tmd, 0, sizeof(struct stats_tmd));
-
-	if (*hinfo.host == '/') {
-		addr = &servaddr_un;
-		addr_len = sizeof(servaddr_un);
-		bzero(addr, addr_len);
-		domain = AF_LOCAL;
-		servaddr_un.sun_family = AF_LOCAL;
-		strncpy(servaddr_un.sun_path, hinfo.host,
-				sizeof(servaddr_un.sun_path) - 1);
-
-	} else {
-		addr = &servaddr;
-		addr_len = sizeof(servaddr);
-		bzero(addr, addr_len);
-		domain = AF_INET;
-		servaddr.sin_family = AF_INET;
-		servaddr.sin_port = htons(hinfo.port);
-		inet_pton(AF_INET, hinfo.host, &servaddr.sin_addr);
-	}
-
-
-	if ((sockfd = socket(domain, SOCK_STREAM, 0)) == -1) {
-		goto writebuf;
-	}
-
-	sprintf(request,
-			"GET %s HTTP/1.0\r\n"
-			"User-Agent: taobot\r\n"
-			"Host: %s\r\n"
-			"Accept:*/*\r\n"
-			"Connection: Close\r\n\r\n",
-			hinfo.uri, hinfo.server_name);
-
-	if ((m = connect(sockfd, (struct sockaddr *) addr, addr_len)) == -1 ) {
-		goto writebuf;
-	}
-
-	if ((send = write(sockfd, request, strlen(request))) == -1) {
-		goto writebuf;
-	}
-
-	if ((stream = fdopen(sockfd, "r")) == NULL) {
-		goto writebuf;
-	}
-
-	while (fgets(line, LEN_4096, stream) != NULL) {
-
-		if (!strncmp(line, " ", 1)) {
-
-			sscanf(line + 1, "%llu %llu %llu %llu",
-					&st_tmd.nprocess, &st_tmd.ncheckcode, &st_tmd.nwait,
-					&st_tmd.ndeny);
-
-			write_flag = 1;
-		}
-	}
-
-writebuf:
-	if (stream) {
-		fclose(stream);
-	}
-
-	if (sockfd != -1) {
-		close(sockfd);
-	}
-
-	if (write_flag) {
-		pos = sprintf(buf, "%lld,%lld,%lld,%lld", st_tmd.nprocess,
-				st_tmd.ncheckcode, st_tmd.nwait, st_tmd.ndeny);
-
-		buf[pos] = '\0';
-		set_mod_record(mod, buf);
-	}
-}
-
-
-void mod_register(struct module *mod)
-{
-	register_mod_fileds(mod, "--tmd", tmd_usage, tmd_info, 4,
-			read_tmd_stats, set_tmd_record);
-}
diff --git a/modules/mod_traffic.c b/modules/mod_traffic.c
index d490206..658b3af 100644
--- a/modules/mod_traffic.c
+++ b/modules/mod_traffic.c
@@ -1,15 +1,19 @@
 #include "tsar.h"
 
-char *traffic_usage = "    --traffic		Net traffic statistics";
+char *traffic_usage = "    --traffic           Net traffic statistics";
 
 /*
  * Structure for traffic infomation.
  */
 struct stats_traffic {
-	unsigned long long bytein;
-	unsigned long long byteout;
-	unsigned long long pktin;
-	unsigned long long pktout;
+    unsigned long long bytein;
+    unsigned long long byteout;
+    unsigned long long pktin;
+    unsigned long long pktout;
+    unsigned long long pkterrin;
+    unsigned long long pktdrpin;
+    unsigned long long pkterrout;
+    unsigned long long pktdrpout;
 } ;
 
 #define STATS_TRAFFIC_SIZE (sizeof(struct stats_traffic))
@@ -18,60 +22,93 @@ struct stats_traffic {
 /*
  * collect traffic infomation
  */
-static void read_traffic_stats(struct module *mod)
+static void
+read_traffic_stats(struct module *mod, char *parameter)
 {
-	FILE *fp;
-	char line[LEN_4096] = {0};
-	char buf[LEN_4096] = {0};
-	memset(buf, 0, LEN_4096);
-	struct stats_traffic total_st, cur_st;
-	memset(&total_st, 0, sizeof(struct stats_traffic));
-	memset(&cur_st, 0, sizeof(struct stats_traffic));
-	char *p = NULL;
-	int len = 0;
+    int                   len = 0, num = 0, n_prefix = 3, i;
+    FILE                 *fp;
+    char                 *p = NULL;
+    char                  line[LEN_4096] = {0};
+    char                  buf[LEN_4096] = {0};
+    char                  mod_parameter[LEN_256], *token;
+    char                 *prefixes[10] = {"eth", "em", "en"};
+    struct stats_traffic  total_st, cur_st;
 
-	if ((fp = fopen(NET_DEV, "r")) == NULL) {
-		return;
-	}
+    memset(buf, 0, LEN_4096);
+    memset(&total_st, 0, sizeof(struct stats_traffic));
+    memset(&cur_st, 0, sizeof(struct stats_traffic));
 
-	memset(&total_st, 0, sizeof(cur_st));
+    if ((fp = fopen(NET_DEV, "r")) == NULL) {
+        return;
+    }
 
-	while (fgets(line, LEN_4096, fp) != NULL) {
-		if (strstr(line, "eth") || strstr(line, "em")) {
-			memset(&cur_st, 0, sizeof(cur_st));
-			p = strchr(line, ':');
-			sscanf(p + 1, "%llu %llu %*u %*u %*u %*u %*u %*u " 
-					"%llu %llu %*u %*u %*u %*u %*u %*u",
-					&cur_st.bytein,
-					&cur_st.pktin,
-					&cur_st.byteout,
-					&cur_st.pktout);
+    memset(&total_st, 0, sizeof(cur_st));
 
-			total_st.bytein  += cur_st.bytein;
-			total_st.byteout += cur_st.byteout;
-			total_st.pktin   += cur_st.pktin;
-			total_st.pktout  += cur_st.pktout;
-		}
-	}
+    if (parameter != NULL) {
+        strncpy(mod_parameter, parameter, LEN_256);
+        token = strtok(mod_parameter, W_SPACE);
+        while (token != NULL && n_prefix < 10) {
+            prefixes[n_prefix++] = token;
+            token = strtok(NULL, W_SPACE);
+        }
+    }
 
-	len = sprintf(buf, "%lld,%lld,%lld,%lld",
-			total_st.bytein,
-			total_st.byteout,
-			total_st.pktin,
-			total_st.pktout);
-	buf[len] = '\0';
-	set_mod_record(mod, buf);
-	fclose(fp);
+    while (fgets(line, LEN_4096, fp) != NULL) {
+        for (i = 0; i < n_prefix; i++) {
+            if (strstr(line, prefixes[i])) {
+                memset(&cur_st, 0, sizeof(cur_st));
+                p = strchr(line, ':');
+                sscanf(p + 1, "%llu %llu %llu %llu %*u %*u %*u %*u "
+                        "%llu %llu %llu %llu %*u %*u %*u %*u",
+                        &cur_st.bytein,
+                        &cur_st.pktin,
+                        &cur_st.pkterrin,
+                        &cur_st.pktdrpin,
+                        &cur_st.byteout,
+                        &cur_st.pktout,
+                        &cur_st.pkterrout,
+                        &cur_st.pktdrpout);
+
+                num++;
+                total_st.bytein    += cur_st.bytein;
+                total_st.byteout   += cur_st.byteout;
+                total_st.pktin     += cur_st.pktin;
+                total_st.pktout    += cur_st.pktout;
+                total_st.pkterrin  += cur_st.pkterrin;
+                total_st.pktdrpin  += cur_st.pktdrpin;
+                total_st.pkterrout += cur_st.pkterrout;
+                total_st.pktdrpout += cur_st.pktdrpout;
+
+                break;
+            }
+        }
+    }
+
+    len = sprintf(buf, "%lld,%lld,%lld,%lld,%lld,%lld",
+            total_st.bytein,
+            total_st.byteout,
+            total_st.pktin,
+            total_st.pktout,
+            total_st.pkterrin + total_st.pkterrout,
+            total_st.pktdrpin + total_st.pktdrpout);
+    buf[len] = '\0';
+    if(num > 0) {
+        set_mod_record(mod, buf);
+    }
+    fclose(fp);
 }
 
 static struct mod_info traffic_info[] ={
-	{" bytin", DETAIL_BIT,  0,  STATS_SUB_INTER},
-	{"bytout", DETAIL_BIT,  0,  STATS_SUB_INTER},
-	{" pktin", SUMMARY_BIT,  0,  STATS_SUB_INTER},
-	{"pktout", SUMMARY_BIT,  0,  STATS_SUB_INTER}
+    {" bytin", SUMMARY_BIT,  0,  STATS_SUB_INTER},
+    {"bytout", SUMMARY_BIT,  0,  STATS_SUB_INTER},
+    {" pktin", DETAIL_BIT,  0,  STATS_SUB_INTER},
+    {"pktout", DETAIL_BIT,  0,  STATS_SUB_INTER},
+    {"pkterr", DETAIL_BIT,  0,  STATS_SUB_INTER},
+    {"pktdrp", DETAIL_BIT,  0,  STATS_SUB_INTER}
 };
 
-void mod_register(struct module *mod)
+void
+mod_register(struct module *mod)
 {
-	register_mod_fileds(mod, "--traffic", traffic_usage, traffic_info, 4, read_traffic_stats, NULL);
+    register_mod_fields(mod, "--traffic", traffic_usage, traffic_info, 6, read_traffic_stats, NULL);
 }
diff --git a/modules/mod_ts_cache.c b/modules/mod_ts_cache.c
deleted file mode 100644
index d28ec0c..0000000
--- a/modules/mod_ts_cache.c
+++ /dev/null
@@ -1,142 +0,0 @@
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <sys/un.h>
-#include "tsar.h"
-
-/*
- * Structure for TS information
- */
-struct stats_ts_cache {
-	unsigned long long hit;
-	unsigned long long ram_hit;
-	unsigned long long band;
-	unsigned long long n_hit;
-	unsigned long long n_ram;
-	unsigned long long n_ssd;
-	unsigned long long ssd_hit;
-};
-//return value type
-const static short int TS_REC_INT = 0;
-const static short int TS_REC_COUNTER = 0;
-const static short int TS_REC_FLOAT = 2;
-const static short int TS_REC_STRING = 3;
-//command type
-const static short int TS_RECORD_GET = 3;
-//records
-const static int LINE_1024 = 1024;
-const static int LINE_4096 = 4096;
-const static char *RECORDS_NAME[]= {
-	"proxy.node.cache_hit_ratio_avg_10s",
-	"proxy.node.cache_hit_mem_ratio_avg_10s",
-	"proxy.node.bandwidth_hit_ratio_avg_10s",
-	"proxy.process.cache.read.success",
-	"proxy.process.cache.ram.read.success",
-	"proxy.process.cache.ssd.read.success"
-};
-//socket patch
-const static char *sock_path = "/var/run/trafficserver/mgmtapisocket";
-//const static char *sock_path = "/usr/local/var/trafficserver/mgmtapisocket";
-
-static char *ts_cache_usage = "    --ts_cache          trafficserver cache statistics";
-
-static struct mod_info ts_cache_info[] = {
-	{"   hit", DETAIL_BIT, 0, STATS_NULL},
-	{"ramhit", DETAIL_BIT, 0, STATS_NULL},
-	{"  band", DETAIL_BIT, 0, STATS_NULL},
-	{" n_hit", HIDE_BIT, 0, STATS_NULL},
-	{" n_ram", HIDE_BIT, 0, STATS_NULL},
-	{" n_ssd", HIDE_BIT, 0, STATS_NULL},
-	{"ssdhit", DETAIL_BIT, 0, STATS_NULL}
-};
-
-void read_ts_cache_stats(struct module *mod)
-{
-	int fd = -1;
-	struct sockaddr_un un;
-	struct stats_ts_cache st_ts;
-	int pos;
-	char buf[LINE_4096];
-	if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) {
-		goto done;
-	}
-	bzero(&st_ts, sizeof(st_ts));
-	bzero(&un, sizeof(un));
-	un.sun_family = AF_UNIX;
-	strcpy(un.sun_path, sock_path);
-	if (connect(fd, (struct sockaddr *)&un, sizeof(un)) < 0) {
-		goto done;
-	}
-
-	int record_len = sizeof(RECORDS_NAME)/sizeof(RECORDS_NAME[0]);
-	int i;
-	const char *info;
-	for ( i = 0; i < record_len; ++i) {
-		info = RECORDS_NAME[i];
-		long int info_len = strlen(info);
-		short int command = TS_RECORD_GET;
-		char write_buf[LINE_1024];
-		*((short int *)&write_buf[0]) = command;
-		*((long int *)&write_buf[2]) = info_len;
-		strcpy(write_buf+6, info);
-		write(fd, write_buf, 2+4+strlen(info));
-
-		short int ret_status;
-		short int ret_type;
-		int read_len = read(fd, buf, LINE_1024);
-
-		if (read_len != -1) {
-			ret_status = *((short int *)&buf[0]);
-			ret_type = *((short int *)&buf[6]);
-
-			if (0 == ret_status) {
-				if (ret_type < 2) {
-					((unsigned long long *)&st_ts)[i] = *((long int *)&buf[8]);
-				} 
-				else if (2 == ret_type) {
-					float ret_val_float = *((float *)&buf[8]);
-					((unsigned long long *)&st_ts)[i] = (int)(ret_val_float * 1000);
-				}
-			}
-		}
-	}
-done:
-	if (-1 != fd)
-		close(fd);
-	pos = sprintf(buf, "%lld,%lld,%lld,%lld,%lld,%lld,0",
-			st_ts.hit,
-			st_ts.ram_hit,
-			st_ts.band,
-			st_ts.n_hit,
-			st_ts.n_ram,
-			st_ts.n_ssd
-		     );
-
-	buf[pos] = '\0';
-	set_mod_record(mod, buf);
-}
-
-
-void set_ts_cache_record(struct module *mod, double st_array[],
-		U_64 pre_array[], U_64 cur_array[], int inter)
-{
-	st_array[0] = cur_array[0]/10.0;
-	st_array[2] = cur_array[2]/10.0;
-
-	// not ssd and sas
-	if (cur_array[5] == 0 && cur_array[1]) {
-		st_array[1] = cur_array[1]/10.0;
-	}
-	else {
-		if (cur_array[3] > pre_array[3]) {
-			st_array[1] = (cur_array[4] - pre_array[4]) * 100.0 / (cur_array[3] - pre_array[3]); 
-			st_array[6] = (cur_array[5] - pre_array[5]) * 100.0 / (cur_array[3] - pre_array[3]); 
-		}
-	}
-}
-
-
-
-void mod_register(struct module *mod)
-{
-	register_mod_fileds(mod, "--ts_cache", ts_cache_usage, ts_cache_info, 7, read_ts_cache_stats, set_ts_cache_record);
-}
diff --git a/modules/mod_ts_client.c b/modules/mod_ts_client.c
deleted file mode 100644
index 1cff31a..0000000
--- a/modules/mod_ts_client.c
+++ /dev/null
@@ -1,145 +0,0 @@
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <sys/un.h>
-#include "tsar.h"
-
-//return value type
-const static short int TS_REC_INT = 0;
-const static short int TS_REC_COUNTER = 0;
-const static short int TS_REC_FLOAT = 2;
-const static short int TS_REC_STRING = 3;
-//command type
-const static short int TS_RECORD_GET = 3;
-//records
-const static int LINE_1024 = 1024;
-const static int LINE_4096 = 4096;
-const static char *RECORDS_NAME[]= {
-	//ts client
-	"proxy.process.http.incoming_requests",
-	"proxy.process.http.total_client_connections",
-	"proxy.node.http.user_agent_total_response_bytes",
-	"proxy.node.http.user_agents_total_transactions_count",
-	"proxy.process.http.total_transactions_time"
-};
-//socket patch
-const static char *sock_path = "/var/run/trafficserver/mgmtapisocket";
-//const static char *sock_path = "/usr/local/var/trafficserver/mgmtapisocket";
-
-/*
- * Structure for TS information
- */
-struct stats_ts {
-	//ts client
-	unsigned long long qps;
-	unsigned long long cons;
-	unsigned long long mbps;
-	unsigned long long uattc;
-	unsigned long long uattt;
-	unsigned long long rt;
-	unsigned long long req_per_con;
-};
-
-static char *ts_usage = "    --ts                trafficserver client statistics";
-
-static struct mod_info ts_info[] = {
-	{"   qps", DETAIL_BIT, 0, STATS_NULL},
-	{"  cons", DETAIL_BIT, 0, STATS_NULL},
-	{"   Bps", DETAIL_BIT, 0, STATS_NULL},
-	{" uattc", HIDE_BIT, 0, STATS_NULL},
-	{" uattt", HIDE_BIT, 0, STATS_NULL},
-	{"    rt", DETAIL_BIT, 0, STATS_NULL},
-	{"   rpc", DETAIL_BIT, 0, STATS_NULL}
-};
-
-void set_ts_record(struct module *mod, double st_array[],
-		U_64 pre_array[], U_64 cur_array[], int inter)
-{
-	int i;
-	for (i = 0; i < 7; ++i) {
-		st_array[i] = 0;
-	}
-	for (i = 0; i < 5; ++i) {
-		if (cur_array[i] >= pre_array[i]) {
-			st_array[i] = (cur_array[i] - pre_array[i]) * 1.0 / inter;
-		}
-	}
-	if (cur_array[0] >= pre_array[0] && cur_array[1] > pre_array[1]) {
-		st_array[6] = st_array[0] / st_array[1];
-	}
-	if (cur_array[4] >= pre_array[4] && cur_array[3] > pre_array[1]) {
-		st_array[5] = (st_array[4] / st_array[3]) / 1000000.0;
-	}
-}
-
-void read_ts_stats(struct module *mod)
-{
-	int fd = -1;
-	struct sockaddr_un un;
-	struct stats_ts st_ts;
-	int pos;
-	char buf[LINE_4096];
-	if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) {
-		goto done;
-	}
-	bzero(&st_ts, sizeof(st_ts));
-	bzero(&un, sizeof(un));
-	un.sun_family = AF_UNIX;
-	strcpy(un.sun_path, sock_path);
-	if (connect(fd, (struct sockaddr *)&un, sizeof(un)) < 0) {
-		goto done;
-	}
-
-	int record_len = sizeof(RECORDS_NAME)/sizeof(RECORDS_NAME[0]);
-	int i;
-	const char *info;
-	for ( i = 0; i < record_len; ++i) {
-		info = RECORDS_NAME[i];
-		long int info_len = strlen(info);
-		short int command = TS_RECORD_GET;
-		char write_buf[LINE_1024];
-		*((short int *)&write_buf[0]) = command;
-		*((long int *)&write_buf[2]) = info_len;
-		strcpy(write_buf+6, info);
-		write(fd, write_buf, 2+4+strlen(info));
-
-		short int ret_status;
-		short int ret_type;
-		long ret_val;
-		int read_len = read(fd, buf, LINE_1024);
-		if (read_len != -1) {
-			ret_status = *((short int *)&buf[0]);
-			ret_type = *((short int *)&buf[6]);
-		}
-		if (0 == ret_status) {
-			if (ret_type < 2) {
-				ret_val= *((long int *)&buf[8]);
-			} else if (2 == ret_type) {
-				float ret_val_float = *((float *)&buf[8]);
-				ret_val_float *= 100;
-				ret_val = (unsigned long long)ret_val_float;
-			} else {
-				goto done;
-			}
-		}
-		((unsigned long long *)&st_ts)[i] = ret_val;
-	}
-done:
-	if (-1 != fd)
-		close(fd);
-	pos = sprintf(buf, "%lld,%lld,%lld,%lld,%lld,%lld,%lld",
-			st_ts.qps,
-			st_ts.cons,
-			st_ts.mbps,
-			st_ts.uattc,
-			st_ts.uattt,
-			st_ts.rt,
-			st_ts.req_per_con
-		     );
-	buf[pos] = '\0';
-	set_mod_record(mod, buf);
-}
-
-void mod_register(struct module *mod)
-{
-	register_mod_fileds(mod, "--ts", ts_usage, ts_info, 7, read_ts_stats, set_ts_record);
-}
diff --git a/modules/mod_ts_codes.c b/modules/mod_ts_codes.c
deleted file mode 100644
index 6abf81a..0000000
--- a/modules/mod_ts_codes.c
+++ /dev/null
@@ -1,157 +0,0 @@
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <sys/un.h>
-#include "tsar.h"
-
-//return value type
-//const static short int TS_REC_INT = 0;
-//const static short int TS_REC_COUNTER = 0;
-//const static short int TS_REC_FLOAT = 2;
-//const static short int TS_REC_STRING = 3;
-//command type
-const static short int TS_RECORD_GET = 3;
-//records
-const static int LINE_1024 = 1024;
-const static int LINE_4096 = 4096;
-const static char *RECORDS_NAME[]= {
-	"proxy.process.http.200_responses",
-	"proxy.process.http.206_responses",
-	"proxy.process.http.301_responses",
-	"proxy.process.http.302_responses",
-	"proxy.process.http.304_responses",
-	"proxy.process.http.400_responses",
-	"proxy.process.http.403_responses",
-	"proxy.process.http.404_responses",
-	"proxy.process.http.500_responses",
-	"proxy.process.http.502_responses",
-	"proxy.process.http.503_responses",
-	"proxy.process.http.504_responses"
-};
-//socket patch
-const static char *sock_path = "/var/run/trafficserver/mgmtapisocket";
-//const static char *sock_path = "/usr/local/var/trafficserver/mgmtapisocket";
-
-/*
- * Structure for TS information
- */
-struct stats_ts_codes {
-	//ts conn
-	unsigned long long code200;
-	unsigned long long code206;
-	unsigned long long code301;
-	unsigned long long code302;
-	unsigned long long code304;
-	unsigned long long code400;
-	unsigned long long code403;
-	unsigned long long code404;
-	unsigned long long code500;
-	unsigned long long code502;
-	unsigned long long code503;
-	unsigned long long code504;
-};
-
-static char *ts_codes_usage = "    --ts_codes          trafficserver statistics on http response codes";
-
-static struct mod_info ts_code_info[] = {
-	{"   200", DETAIL_BIT, 0, STATS_NULL},
-	{"   206", DETAIL_BIT, 0, STATS_NULL},
-	{"   301", DETAIL_BIT, 0, STATS_NULL},
-	{"   302", DETAIL_BIT, 0, STATS_NULL},
-	{"   304", DETAIL_BIT, 0, STATS_NULL},
-	{"   400", DETAIL_BIT, 0, STATS_NULL},
-	{"   403", DETAIL_BIT, 0, STATS_NULL},
-	{"   404", DETAIL_BIT, 0, STATS_NULL},
-	{"   500", DETAIL_BIT, 0, STATS_NULL},
-	{"   502", DETAIL_BIT, 0, STATS_NULL},
-	{"   503", DETAIL_BIT, 0, STATS_NULL},
-	{"   504", DETAIL_BIT, 0, STATS_NULL},
-};
-
-void set_ts_code_record(struct module *mod, double st_array[],
-		U_64 pre_array[], U_64 cur_array[], int inter)
-{
-	int i;
-	for (i = 0; i < 12; i++) {
-		if (cur_array[i] >= pre_array[i]) {
-			st_array[i] = (cur_array[i] - pre_array[i]) * 1.0 / inter;
-		}
-	}
-}
-
-void read_ts_code_stats(struct module *mod)
-{
-	int fd = -1;
-	struct sockaddr_un un;
-	struct stats_ts_codes st_ts;
-	int pos;
-	char buf[LINE_4096];
-	if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) {
-		goto done;
-	}
-	bzero(&st_ts, sizeof(st_ts));
-	bzero(&un, sizeof(un));
-	un.sun_family = AF_UNIX;
-	strcpy(un.sun_path, sock_path);
-	if (connect(fd, (struct sockaddr *)&un, sizeof(un)) < 0) {
-		goto done;
-	}
-
-	int record_len = sizeof(RECORDS_NAME)/sizeof(RECORDS_NAME[0]);
-	int i;
-	const char *info;
-	for ( i = 0; i < record_len; ++i) {
-		info = RECORDS_NAME[i];
-		long int info_len = strlen(info);
-		short int command = TS_RECORD_GET;
-		char write_buf[LINE_1024];
-		*((short int *)&write_buf[0]) = command;
-		*((long int *)&write_buf[2]) = info_len;
-		strcpy(write_buf+6, info);
-		write(fd, write_buf, 2+4+strlen(info));
-
-		short int ret_status = 0;
-		short int ret_type = 0;
-		long ret_val = 0;
-		int read_len = read(fd, buf, LINE_1024);
-		if (read_len != -1) {
-			ret_status = *((short int *)&buf[0]);
-			ret_type = *((short int *)&buf[6]);
-		}
-		if (0 == ret_status) {
-			if (ret_type < 2) {
-				ret_val= *((long int *)&buf[8]);
-			} else if (2 == ret_type) {
-				float ret_val_float = *((float *)&buf[8]);
-				ret_val_float *= 100;
-				ret_val = (unsigned long long)ret_val_float;
-			} else {
-				goto done;
-			}
-		}
-		((unsigned long long *)&st_ts)[i] = ret_val;
-	}
-done:
-	if (-1 != fd)
-		close(fd);
-	pos = sprintf(buf, "%lld,%lld,%lld,%lld,%lld,%lld,%lld,%lld,%lld,%lld,%lld,%lld",
-			st_ts.code200,
-			st_ts.code206,
-			st_ts.code301,
-			st_ts.code302,
-			st_ts.code304,
-			st_ts.code400,
-			st_ts.code403,
-			st_ts.code404,
-			st_ts.code500,
-			st_ts.code502,
-			st_ts.code503,
-			st_ts.code504
-		     );
-	buf[pos] = '\0';
-	set_mod_record(mod, buf);
-}
-
-void mod_register(struct module *mod)
-{
-	register_mod_fileds(mod, "--ts_codes", ts_codes_usage, ts_code_info, 12, read_ts_code_stats, set_ts_code_record);
-}
diff --git a/modules/mod_ts_conn.c b/modules/mod_ts_conn.c
deleted file mode 100644
index 2f6858d..0000000
--- a/modules/mod_ts_conn.c
+++ /dev/null
@@ -1,135 +0,0 @@
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <sys/un.h>
-#include "tsar.h"
-
-//return value type
-const static short int TS_REC_INT = 0;
-const static short int TS_REC_COUNTER = 0;
-const static short int TS_REC_FLOAT = 2;
-const static short int TS_REC_STRING = 3;
-//command type
-const static short int TS_RECORD_GET = 3;
-//records
-const static int LINE_1024 = 1024;
-const static int LINE_4096 = 4096;
-const static char *RECORDS_NAME[]= {
-	"proxy.process.http.current_client_connections",
-	"proxy.process.http.current_server_connections",
-	"proxy.process.http.current_cache_connections",
-	"proxy.process.net.connections_currently_open",
-	"proxy.process.http.current_active_client_connections",
-	"proxy.process.http.current_client_transactions",
-	"proxy.process.http.current_server_transactions"
-};
-//socket patch
-const static char *sock_path = "/var/run/trafficserver/mgmtapisocket";
-//const static char *sock_path = "/usr/local/var/trafficserver/mgmtapisocket";
-
-/*
- * Structure for TS information
- */
-struct stats_ts_conn {
-	//ts conn
-	unsigned long long c_client;
-	unsigned long long c_server;
-	unsigned long long c_cache;
-	unsigned long long c_open;
-	unsigned long long c_a_client;
-	unsigned long long t_client;
-	unsigned long long t_server;
-};
-
-static char *ts_conn_usage = "    --ts                trafficserver connection statistics";
-
-static struct mod_info ts_conn_info[] = {
-	{"client", DETAIL_BIT, 0, STATS_NULL},
-	{"server", DETAIL_BIT, 0, STATS_NULL},
-	{" cache", DETAIL_BIT, 0, STATS_NULL},
-	{"  open", DETAIL_BIT, 0, STATS_NULL},
-	{" c_act", DETAIL_BIT, 0, STATS_NULL},
-	{" t_cli", DETAIL_BIT, 0, STATS_NULL},
-	{" t_srv", DETAIL_BIT, 0, STATS_NULL},
-};
-
-void set_ts_conn_record(struct module *mod, double st_array[],
-		U_64 pre_array[], U_64 cur_array[], int inter)
-{
-	int i;
-	for (i = 0; i < 7; i++) {
-		st_array[i] = cur_array[i];
-	}
-}
-
-void read_ts_conn_stats(struct module *mod)
-{
-	int fd = -1;
-	struct sockaddr_un un;
-	struct stats_ts_conn st_ts;
-	int pos;
-	char buf[LINE_4096];
-	if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) {
-		goto done;
-	}
-	bzero(&st_ts, sizeof(st_ts));
-	bzero(&un, sizeof(un));
-	un.sun_family = AF_UNIX;
-	strcpy(un.sun_path, sock_path);
-	if (connect(fd, (struct sockaddr *)&un, sizeof(un)) < 0) {
-		goto done;
-	}
-
-	int record_len = sizeof(RECORDS_NAME)/sizeof(RECORDS_NAME[0]);
-	int i;
-	const char *info;
-	for ( i = 0; i < record_len; ++i) {
-		info = RECORDS_NAME[i];
-		long int info_len = strlen(info);
-		short int command = TS_RECORD_GET;
-		char write_buf[LINE_1024];
-		*((short int *)&write_buf[0]) = command;
-		*((long int *)&write_buf[2]) = info_len;
-		strcpy(write_buf+6, info);
-		write(fd, write_buf, 2+4+strlen(info));
-
-		short int ret_status;
-		short int ret_type;
-		long ret_val;
-		int read_len = read(fd, buf, LINE_1024);
-		if (read_len != -1) {
-			ret_status = *((short int *)&buf[0]);
-			ret_type = *((short int *)&buf[6]);
-		}
-		if (0 == ret_status) {
-			if (ret_type < 2) {
-				ret_val= *((long int *)&buf[8]);
-			} else if (2 == ret_type) {
-				float ret_val_float = *((float *)&buf[8]);
-				ret_val_float *= 100;
-				ret_val = (unsigned long long)ret_val_float;
-			} else {
-				goto done;
-			}
-		}
-		((unsigned long long *)&st_ts)[i] = ret_val;
-	}
-done:
-	if (-1 != fd)
-		close(fd);
-	pos = sprintf(buf, "%lld,%lld,%lld,%lld,%lld,%lld,%lld",
-			st_ts.c_client,
-			st_ts.c_server,
-			st_ts.c_cache,
-			st_ts.c_open,
-			st_ts.c_a_client,
-			st_ts.t_client,
-			st_ts.t_server
-		     );
-	buf[pos] = '\0';
-	set_mod_record(mod, buf);
-}
-
-void mod_register(struct module *mod)
-{
-	register_mod_fileds(mod, "--ts_conn", ts_conn_usage, ts_conn_info, 7, read_ts_conn_stats, set_ts_conn_record);
-}
diff --git a/modules/mod_ts_err.c b/modules/mod_ts_err.c
deleted file mode 100644
index 41cacfb..0000000
--- a/modules/mod_ts_err.c
+++ /dev/null
@@ -1,147 +0,0 @@
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <sys/un.h>
-#include "tsar.h"
-
-/*
- * Structure for TS information
- */
-struct stats_ts_err {
-	//ts error
-	unsigned long long miss_host;
-	unsigned long long aborts;
-	unsigned long long pre_accept_hangups;
-	unsigned long long empty_hangups;
-	unsigned long long early_hangups;
-	unsigned long long con_fail;
-	unsigned long long other;
-	unsigned long long hangup;//sum
-};
-//return value type
-const static short int TS_REC_INT = 0;
-const static short int TS_REC_COUNTER = 0;
-const static short int TS_REC_FLOAT = 2;
-const static short int TS_REC_STRING = 3;
-//command type
-const static short int TS_RECORD_GET = 3;
-//records
-const static int LINE_1024 = 1024;
-const static int LINE_4096 = 4096;
-const static char *RECORDS_NAME[]= {
-	//ts error
-	"proxy.process.http.missing_host_hdr",
-	"proxy.process.http.transaction_counts.errors.aborts",
-	"proxy.process.http.transaction_counts.errors.pre_accept_hangups",
-	"proxy.process.http.transaction_counts.errors.empty_hangups",
-	"proxy.process.http.transaction_counts.errors.early_hangups",
-	"proxy.process.http.transaction_counts.errors.connect_failed",
-	"proxy.process.http.transaction_counts.errors.other"//float
-};
-//socket patch
-const static char *sock_path = "/var/run/trafficserver/mgmtapisocket";
-//const static char *sock_path = "/usr/local/var/trafficserver/mgmtapisocket";
-
-static char *ts_err_usage = "    --ts_err            trafficserver error statistics";
-
-static struct mod_info ts_err_info[] = {
-	{"  host", DETAIL_BIT, 0, STATS_NULL},
-	{" abort", DETAIL_BIT, 0, STATS_NULL},
-	{"   p_h", HIDE_BIT, 0, STATS_NULL},
-	{" emp_h", HIDE_BIT, 0, STATS_NULL},
-	{" ear_h", HIDE_BIT, 0, STATS_NULL},
-	{"  conn", DETAIL_BIT, 0, STATS_NULL},
-	{" other", DETAIL_BIT, 0, STATS_NULL},
-	{"hangup", SUMMARY_BIT, 0, STATS_NULL}
-};
-
-void set_ts_err_record(struct module *mod, double st_array[],
-		U_64 pre_array[], U_64 cur_array[], int inter)
-{
-	int i;
-	for (i = 0; i < 8; ++i) {
-		st_array[i] = 0;
-	}
-	for (i = 0; i < 6; ++i) {
-		if (cur_array[i] >= pre_array[i]) {
-			st_array[i] = (cur_array[i] - pre_array[i]) * 1.0 / inter;
-		}
-	}
-	if (cur_array[6] >= pre_array[6]) {
-		st_array[6] = (cur_array[6] - pre_array[6]) * 1.0 / (inter * 100);
-	}
-	st_array[7] = st_array[2] + st_array[3] + st_array[4];
-}
-
-void read_ts_err_stats(struct module *mod)
-{
-	int fd = -1;
-	struct sockaddr_un un;
-	struct stats_ts_err st_ts;
-	int pos;
-	char buf[LINE_4096];
-	if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) {
-		goto done;
-	}
-	bzero(&st_ts, sizeof(st_ts));
-	bzero(&un, sizeof(un));
-	un.sun_family = AF_UNIX;
-	strcpy(un.sun_path, sock_path);
-	if (connect(fd, (struct sockaddr *)&un, sizeof(un)) < 0) {
-		goto done;
-	}
-
-	int record_len = sizeof(RECORDS_NAME)/sizeof(RECORDS_NAME[0]);
-	int i;
-	const char *info;
-	for ( i = 0; i < record_len; ++i) {
-		info = RECORDS_NAME[i];
-		long int info_len = strlen(info);
-		short int command = TS_RECORD_GET;
-		char write_buf[LINE_1024];
-		*((short int *)&write_buf[0]) = command;
-		*((long int *)&write_buf[2]) = info_len;
-		strcpy(write_buf+6, info);
-		write(fd, write_buf, 2+4+strlen(info));
-
-		short int ret_status;
-		short int ret_type;
-		long ret_val;
-		int read_len = read(fd, buf, LINE_1024);
-		if (read_len != -1) {
-			ret_status = *((short int *)&buf[0]);
-			ret_type = *((short int *)&buf[6]);
-		}
-		if (0 == ret_status) {
-			if (ret_type < 2) {
-				ret_val= *((long int *)&buf[8]);
-			} else if (2 == ret_type) {
-				float ret_val_float = *((float *)&buf[8]);
-				ret_val_float *= 100;
-				ret_val = (unsigned long long)ret_val_float;
-			} else {
-				goto done;
-			}
-		}
-		((unsigned long long *)&st_ts)[i] = ret_val;
-	}
-done:
-	if (-1 != fd)
-		close(fd);
-	pos = sprintf(buf, "%lld,%lld,%lld,%lld,%lld,%lld,%lld,%lld",
-			st_ts.miss_host,
-			st_ts.aborts,
-			st_ts.pre_accept_hangups,
-			st_ts.empty_hangups,
-			st_ts.early_hangups,
-			st_ts.con_fail,
-			st_ts.other,
-			st_ts.hangup
-		     );
-	buf[pos] = '\0';
-	set_mod_record(mod, buf);
-}
-
-void mod_register(struct module *mod)
-{
-	register_mod_fileds(mod, "--ts_err", ts_err_usage, ts_err_info, 8, read_ts_err_stats, set_ts_err_record);
-}
diff --git a/modules/mod_ts_os.c b/modules/mod_ts_os.c
deleted file mode 100644
index 9087c47..0000000
--- a/modules/mod_ts_os.c
+++ /dev/null
@@ -1,130 +0,0 @@
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <sys/un.h>
-#include "tsar.h"
-
-/*
- * Structure for TS information
- */
-struct stats_ts_os {
-	//ts os
-	unsigned long long os_qps;
-	unsigned long long os_cons;
-	unsigned long long os_mbps;
-	unsigned long long os_req_per_con;
-};
-//return value type
-const static short int TS_REC_INT = 0;
-const static short int TS_REC_COUNTER = 0;
-const static short int TS_REC_FLOAT = 2;
-const static short int TS_REC_STRING = 3;
-//command type
-const static short int TS_RECORD_GET = 3;
-//records
-const static int LINE_1024 = 1024;
-const static int LINE_4096 = 4096;
-const static char *RECORDS_NAME[]= {
-	//ts origin server
-	"proxy.process.http.outgoing_requests",
-	"proxy.process.http.total_server_connections",
-	"proxy.node.http.origin_server_total_response_bytes"
-};
-//socket patch
-const static char *sock_path = "/var/run/trafficserver/mgmtapisocket";
-//const static char *sock_path = "/usr/local/var/trafficserver/mgmtapisocket";
-
-static char *ts_os_usage = "    --ts_os             trafficserver origin server info statistics";
-
-static struct mod_info ts_os_info[] = {
-	{"   qps", DETAIL_BIT, 0, STATS_NULL},
-	{"  cons", DETAIL_BIT, 0, STATS_NULL},
-	{"  mbps", DETAIL_BIT, 0, STATS_NULL},
-	{"   rpc", DETAIL_BIT, 0, STATS_NULL},
-};
-
-void set_ts_os_record(struct module *mod, double st_array[],
-		U_64 pre_array[], U_64 cur_array[], int inter)
-{
-	int i;
-	for (i = 0; i < 4; ++i) {
-		st_array[i] = 0;
-	}
-	for (i = 0; i < 3; ++i) {
-		if (cur_array[i] >= pre_array[i]) {
-			st_array[i] = (cur_array[i] - pre_array[i]) * 1.0 / inter;
-		}
-	}
-	if (cur_array[0] >= pre_array[0] && cur_array[1] > pre_array[1]) {
-		st_array[3] = st_array[0]/st_array[1];
-	}
-}
-
-void read_ts_os_stats(struct module *mod)
-{
-	int fd = -1;
-	struct sockaddr_un un;
-	struct stats_ts_os st_ts;
-	int pos;
-	char buf[LINE_4096];
-	if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) {
-		goto done;
-	}
-	bzero(&st_ts, sizeof(st_ts));
-	bzero(&un, sizeof(un));
-	un.sun_family = AF_UNIX;
-	strcpy(un.sun_path, sock_path);
-	if (connect(fd, (struct sockaddr *)&un, sizeof(un)) < 0) {
-		goto done;
-	}
-
-	int record_len = sizeof(RECORDS_NAME)/sizeof(RECORDS_NAME[0]);
-	int i;
-	const char *info;
-	for ( i = 0; i < record_len; ++i) {
-		info = RECORDS_NAME[i];
-		long int info_len = strlen(info);
-		short int command = TS_RECORD_GET;
-		char write_buf[LINE_1024];
-		*((short int *)&write_buf[0]) = command;
-		*((long int *)&write_buf[2]) = info_len;
-		strcpy(write_buf+6, info);
-		write(fd, write_buf, 2+4+strlen(info));
-
-		short int ret_status;
-		short int ret_type;
-		long ret_val;
-		int read_len = read(fd, buf, LINE_1024);
-		if (read_len != -1) {
-			ret_status = *((short int *)&buf[0]);
-			ret_type = *((short int *)&buf[6]);
-		}
-		if (0 == ret_status) {
-			if (ret_type < 2) {
-				ret_val= *((long int *)&buf[8]);
-			} else if (2 == ret_type) {
-				float ret_val_float = *((float *)&buf[8]);
-				ret_val_float *= 100;
-				ret_val = (unsigned long long)ret_val_float;
-			} else {
-				goto done;
-			}
-		}
-		((unsigned long long *)&st_ts)[i] = ret_val;
-	}
-done:
-	if (-1 != fd)
-		close(fd);
-	pos = sprintf(buf, "%lld,%lld,%lld,%lld",
-			st_ts.os_qps,
-			st_ts.os_cons,
-			st_ts.os_mbps,
-			st_ts.os_req_per_con
-		     );
-	buf[pos] = '\0';
-	set_mod_record(mod, buf);
-}
-
-void mod_register(struct module *mod)
-{
-	register_mod_fileds(mod, "--ts_os", ts_os_usage, ts_os_info, 4, read_ts_os_stats, set_ts_os_record);
-}
diff --git a/modules/mod_ts_storage.c b/modules/mod_ts_storage.c
deleted file mode 100644
index e40f550..0000000
--- a/modules/mod_ts_storage.c
+++ /dev/null
@@ -1,125 +0,0 @@
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <sys/un.h>
-#include "tsar.h"
-
-/* * Structure for TS storage information
- */
-struct stats_ts_storage {
-	//ts storage
-	unsigned long long ram_used_space;
-	unsigned long long disk_used_space;
-	unsigned long long dirs_used;
-	unsigned long long avg_obj_size;
-};
-//return value type
-const static short int TS_REC_INT = 0;
-const static short int TS_REC_COUNTER = 0;
-const static short int TS_REC_FLOAT = 2;
-const static short int TS_REC_STRING = 3;
-//command type
-const static short int TS_RECORD_GET = 3;
-//records
-const static int LINE_1024 = 1024;
-const static int LINE_4096 = 4096;
-const static char *RECORDS_NAME[]= {
-	//ts storage 
-	"proxy.process.cache.ram_cache.bytes_used",
-	"proxy.process.cache.bytes_used",
-	"proxy.process.cache.direntries.used"
-};
-//socket patch
-const static char *sock_path = "/var/run/trafficserver/mgmtapisocket";
-//const static char *sock_path = "/usr/local/var/trafficserver/mgmtapisocket";
-
-static char *ts_storage_usage = "    --ts_storage        trafficserver storage statistics";
-
-static struct mod_info ts_storage_info[] = {
-	{"   ram", DETAIL_BIT, 0, STATS_NULL},
-	{"  disk", DETAIL_BIT, 0, STATS_NULL},
-	{"  objs", DETAIL_BIT, 0, STATS_NULL},
-	{"  size", DETAIL_BIT, 0, STATS_NULL}
-};
-
-void set_ts_storage_record(struct module *mod, double st_array[],
-		U_64 pre_array[], U_64 cur_array[], int inter)
-{
-	int i;
-	st_array[3] = 0;
-	for (i = 0; i < 3; ++i) {
-		st_array[i] = cur_array[i];
-	}
-	if (cur_array[2] != 0) {
-		st_array[3] = st_array[1]/st_array[2];
-	}
-}
-
-void read_ts_storage_stats(struct module *mod)
-{
-	int fd = -1;
-	struct sockaddr_un un;
-	struct stats_ts_storage st_ts;
-	int pos;
-	char buf[LINE_4096];
-	if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) {
-		goto done;
-	}
-	bzero(&st_ts, sizeof(st_ts));
-	bzero(&un, sizeof(un));
-	un.sun_family = AF_UNIX;
-	strcpy(un.sun_path, sock_path);
-	if (connect(fd, (struct sockaddr *)&un, sizeof(un)) < 0) {
-		goto done;
-	}
-
-	int record_len = sizeof(RECORDS_NAME)/sizeof(RECORDS_NAME[0]);
-	int i;
-	const char *info;
-	for ( i = 0; i < record_len; ++i) {
-		info = RECORDS_NAME[i];
-		long int info_len = strlen(info);
-		short int command = TS_RECORD_GET;
-		char write_buf[LINE_1024];
-		*((short int *)&write_buf[0]) = command;
-		*((long int *)&write_buf[2]) = info_len;
-		strcpy(write_buf+6, info);
-		write(fd, write_buf, 2+4+strlen(info));
-
-		short int ret_status;
-		short int ret_type;
-		long ret_val;
-		int read_len = read(fd, buf, LINE_1024);
-		if (read_len != -1) {
-			ret_status = *((short int *)&buf[0]);
-			ret_type = *((short int *)&buf[6]);
-		}
-		if (0 == ret_status) {
-			if (ret_type < 2) {
-				ret_val= *((long int *)&buf[8]);
-			} else if (2 == ret_type) {
-				float ret_val_float = *((float *)&buf[8]);
-				ret_val_float *= 100;
-				ret_val = (unsigned long long)ret_val_float;
-			} else {
-				goto done;
-			}
-		}
-		((unsigned long long *)&st_ts)[i] = ret_val;
-	}
-done:
-	if (-1 != fd)
-		close(fd);
-	pos = sprintf(buf, "%lld,%lld,%lld,%lld",
-			st_ts.ram_used_space,
-			st_ts.disk_used_space,
-			st_ts.dirs_used,
-			st_ts.avg_obj_size
-		     );
-	buf[pos] = '\0';
-	set_mod_record(mod, buf);
-}
-
-void mod_register(struct module *mod)
-{
-	register_mod_fileds(mod, "--ts_storage", ts_storage_usage, ts_storage_info, 4, read_ts_storage_stats, set_ts_storage_record);
-}
diff --git a/modules/mod_udp.c b/modules/mod_udp.c
index 1298572..e1f63ad 100644
--- a/modules/mod_udp.c
+++ b/modules/mod_udp.c
@@ -1,71 +1,73 @@
 #include "tsar.h"
 
-#define UDP_DETAIL_HDR(d)			\
-	"  idgm"d"  odgm"d"noport"d"idmerr"	
+#define UDP_DETAIL_HDR(d)           \
+    "  idgm"d"  odgm"d"noport"d"idmerr"
 
 char *udp_usage =
 "    --udp               UDP traffic     (v4)";
 
 /* Structure for UDP statistics */
 struct stats_udp {
-	unsigned long long InDatagrams;
-	unsigned long long OutDatagrams;
-	unsigned long long NoPorts;     
-	unsigned long long InErrors;
+    unsigned long long InDatagrams;
+    unsigned long long OutDatagrams;
+    unsigned long long NoPorts;
+    unsigned long long InErrors;
 };
 
 #define STATS_UDP_SIZE      (sizeof(struct stats_udp))
 
-void read_udp_stats(struct module *mod)
+void
+read_udp_stats(struct module *mod)
 {
-	FILE *fp;
-	char line[LEN_1024];
-	char buf[LEN_1024];
-	memset(buf, 0, LEN_1024);
-	int sw = FALSE;
-	struct stats_udp st_udp;
-	memset(&st_udp, 0, sizeof(struct stats_udp));
-	if ((fp = fopen(NET_SNMP, "r")) == NULL) {
-		return;
-	}
+    int               sw = FALSE;
+    FILE             *fp;
+    char              line[LEN_1024];
+    char              buf[LEN_1024];
+    struct stats_udp  st_udp;
 
-	while (fgets(line, LEN_1024, fp) != NULL) {
+    memset(buf, 0, LEN_1024);
+    memset(&st_udp, 0, sizeof(struct stats_udp));
+    if ((fp = fopen(NET_SNMP, "r")) == NULL) {
+        return;
+    }
 
-		if (!strncmp(line, "Udp:", 4)) {
-			if (sw) {
-				sscanf(line + 4, "%llu %llu %llu %llu",
-						&st_udp.InDatagrams,
-						&st_udp.NoPorts,
-						&st_udp.InErrors,
-						&st_udp.OutDatagrams);
-				break;
-			}
-			else {
-				sw = TRUE;
-			}
-		}
-	}
+    while (fgets(line, LEN_1024, fp) != NULL) {
 
-	fclose(fp);
+        if (!strncmp(line, "Udp:", 4)) {
+            if (sw) {
+                sscanf(line + 4, "%llu %llu %llu %llu",
+                        &st_udp.InDatagrams,
+                        &st_udp.NoPorts,
+                        &st_udp.InErrors,
+                        &st_udp.OutDatagrams);
+                break;
 
-	int pos = sprintf(buf, "%lld,%lld,%lld,%lld",
-			st_udp.InDatagrams,
-			st_udp.NoPorts,
-			st_udp.InErrors,
-			st_udp.OutDatagrams);
-	buf[pos] = '\0';
-	set_mod_record(mod, buf);
+            } else {
+                sw = TRUE;
+            }
+        }
+    }
+
+    fclose(fp);
+
+    int pos = sprintf(buf, "%lld,%lld,%lld,%lld",
+            st_udp.InDatagrams,
+            st_udp.OutDatagrams,
+            st_udp.NoPorts,
+            st_udp.InErrors);
+    buf[pos] = '\0';
+    set_mod_record(mod, buf);
 }
 
 static struct mod_info udp_info[] = {
-	{"  idgm", DETAIL_BIT,  0,  STATS_SUB_INTER},
-	{"  odgm", DETAIL_BIT,  0,  STATS_SUB_INTER},
-	{"noport", DETAIL_BIT,  0,  STATS_SUB_INTER},
-	{"idmerr", DETAIL_BIT,  0,  STATS_SUB_INTER},
+    {"  idgm", DETAIL_BIT,  0,  STATS_SUB_INTER},
+    {"  odgm", DETAIL_BIT,  0,  STATS_SUB_INTER},
+    {"noport", DETAIL_BIT,  0,  STATS_SUB_INTER},
+    {"idmerr", DETAIL_BIT,  0,  STATS_SUB_INTER},
 };
 
-void mod_register(struct module *mod)
+void
+mod_register(struct module *mod)
 {
-	register_mod_fileds(mod, "--udp", udp_usage, udp_info, 4, read_udp_stats, NULL);
+    register_mod_fields(mod, "--udp", udp_usage, udp_info, 4, read_udp_stats, NULL);
 }
-
diff --git a/rpm/tsar-VER.txt b/rpm/tsar-VER.txt
index 7ec1d6d..8a1af3b 100644
--- a/rpm/tsar-VER.txt
+++ b/rpm/tsar-VER.txt
@@ -1 +1 @@
-2.1.0
+2.1.29
diff --git a/rpm/tsar-build.sh b/rpm/tsar-build.sh
old mode 100644
new mode 100755
index d3963a5..50c949f
--- a/rpm/tsar-build.sh
+++ b/rpm/tsar-build.sh
@@ -6,6 +6,7 @@ export name=$2
 export version=$3
 export release=$4
 
+
 TOP_DIR="/tmp/.rpm_create_"$2"_"`whoami`
 
 LANG=C
@@ -18,40 +19,32 @@ usage()
   exit 0
 }
 
-svn_path="Unknown_path"
-svn_revision="Unknown_revision"
-svn_info()
+git_path="Unknown_path"
+git_revision=$release
+git_info()
 {
-  str=`svn info ../ 2>/dev/null |
-  awk -F': ' '{if($1=="URL") print $2}'`
-
-  if [ -z "$str" ]; then return; fi
-
-  svn_path=$str
-  str=`svn info ../ 2>/dev/null |
-  awk -F': ' '{if($1=="Last Changed Rev") print $2}'`
-
-  if [ -z "$str" ]; then
-    echo "!! Please upgrade your subversion: sudo yum install subversion"
-    return;
-  fi
-
-  svn_revision=$str
+  base=19000
+  git_version=`git rev-list --all|wc -l`
+  git_revision=`expr $git_version + $base`
+  echo $git_revision
 }
 
-svn_info
+building_tag()
+{
+    git_revision=$release.`git log --pretty=oneline -1 |cut -c1-7`
+    echo "new subversion is:"$version
+}
+building_tag
+##git_info
 
-if [ `cat /etc/redhat-release|cut -d " " -f 7|cut -d "." -f 1` = 4 ]
-then
-        release="$svn_revision".el4
-elif [ `cat /etc/redhat-release|cut -d " " -f 7|cut -d "." -f 1` = 5 ]
+echo "/etc/redhat-release:"
+cat /etc/redhat-release
+releasever=$(cut -d: -f5 /etc/system-release-cpe)
+if [[ -n "$releasever" ]]
 then
-        release="$svn_revision".el5
-elif [ `cat /etc/redhat-release|cut -d " " -f 7|cut -d "." -f 1` = 6 ]
-then
-        release="$svn_revision".el6
+        release="$git_revision".el$releasever
 else
-        release="$svn_revision".el5
+        release="$git_revision".el7
 fi
 
 RPM_MACROS=$HOME/.rpmmacros
@@ -63,8 +56,8 @@ fi
 echo "%_topdir $TOP_DIR" > $RPM_MACROS
 echo "%packager " `whoami` >> $RPM_MACROS
 echo "%vendor TaoBao Inc." >> $RPM_MACROS
-echo "%_svn_path $svn_path" >> $RPM_MACROS
-echo "%_svn_revision $svn_revision" >> $RPM_MACROS
+echo "%_git_path $git_path" >> $RPM_MACROS
+echo "%_git_revision $git_revision" >> $RPM_MACROS
 echo "%_release $release" >> $RPM_MACROS
 echo "%debug_package %{nil}" >> $RPM_MACROS
 
@@ -79,8 +72,7 @@ mkdir -p $TOP_DIR/SPECS
 export fullname=$name-$version
 
 ln -s . $fullname
-tar --exclude=$fullname/*/.svn \
-    --exclude=$fullname/$fullname \
+tar --exclude=$fullname/$fullname \
     --exclude=$fullname/$fullname.tar.gz \
     -cf - $fullname/* | gzip -c9 >$fullname.tar.gz
 cp $fullname.tar.gz $TOP_DIR/SOURCES
@@ -90,12 +82,12 @@ rm $fullname.tar.gz
 rm -rf $fullname
 
 ## create spec file from template
-sed -e "s/_VERSION_/$version/g" -e "s/_RELEASE_/$release/g"  -e "s/SVN_REVISION/$svn_revision/g" < rpm/$name.spec.in > $TOP_DIR/SPECS/$name.spec
+sed -e "s/_VERSION_/$version/g" -e "s/_RELEASE_/$release/g"  -e "s/SVN_REVISION/$git_revision/g" < rpm/$name.spec.in > $TOP_DIR/SPECS/$name.spec
 
 rpmbuild --ba $TOP_DIR/SPECS/$name.spec
 
 find $TOP_DIR/RPMS -name "*.rpm"  -exec mv {} ./rpm \;
-
+echo "dir: $TOP_DIR"
 rm -rf $TOP_DIR $RPM_MACROS
 if [ -e $RPM_MACROS.bak ]; then
   mv -f $RPM_MACROS.bak $RPM_MACROS
diff --git a/rpm/tsar-devel.spec b/rpm/tsar-devel.spec
new file mode 100644
index 0000000..afc8f68
--- /dev/null
+++ b/rpm/tsar-devel.spec
@@ -0,0 +1,35 @@
+Name: tsar-devel
+Version: 2.1.1
+Release: %(echo $RELEASE)%{?dist}
+Summary: Taobao Tsar Devel
+Group: Taobao/Common
+License: Commercial
+
+%description
+devel package include tsar header files and module template for the development
+
+%install
+rm -rf $RPM_BUILD_ROOT
+mkdir -p $RPM_BUILD_ROOT/usr/bin
+cd $OLDPWD/../
+make DESTDIR=$RPM_BUILD_ROOT tsardevel
+make DESTDIR=$RPM_BUILD_ROOT tsarluadevel
+
+%clean
+rm -rf $RPM_BUILD_ROOT
+
+%files
+%defattr(-,root,root)
+/usr/local/tsar/devel/tsar.h
+/usr/local/tsar/devel/Makefile.test
+/usr/local/tsar/devel/mod_test.c
+/usr/local/tsar/devel/mod_test.conf
+/usr/local/tsar/luadevel/Makefile.test
+/usr/local/tsar/luadevel/mod_lua_test.lua
+/usr/local/tsar/luadevel/mod_lua_test.conf
+%attr(755,root,root)
+/usr/bin/tsardevel
+/usr/bin/tsarluadevel
+
+%changelog
+
diff --git a/rpm/tsar.spec b/rpm/tsar.spec
new file mode 100644
index 0000000..357251a
--- /dev/null
+++ b/rpm/tsar.spec
@@ -0,0 +1,66 @@
+Name: tsar
+Version: 2.1.1
+Release: 19200.aone
+Summary: Taobao System Activity Reporter
+URL: https://github.com/alibaba/tsar
+Group: Taobao/Common
+License: Commercial
+BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
+Source: tsar-%{version}.tar.gz
+
+%description
+tsar is Taobao monitor tool for collect system activity status, and report it.
+It have a plugin system that is easy for collect plugin development. and may
+setup different output target such as local logfile and remote nagios host.
+
+%prep
+%setup -q
+
+%build
+make clean;make
+
+%install
+
+rm -rf %{buildroot}
+mkdir -p %{buildroot}/usr/local/tsar/
+mkdir -p %{buildroot}/usr/local/tsar/modules/
+mkdir -p %{buildroot}/usr/local/tsar/conf/
+mkdir -p %{buildroot}/usr/local/man/man8/
+mkdir -p %{buildroot}/etc/logrotate.d/
+mkdir -p %{buildroot}/etc/tsar/
+mkdir -p %{buildroot}/etc/cron.d/
+mkdir -p %{buildroot}/usr/bin
+
+install -p -D -m 0755 src/tsar  %{buildroot}/usr/bin/tsar
+install -p -D -m 0644 conf/tsar.conf %{buildroot}/etc/tsar/tsar.conf
+install -p -D -m 0644 modules/*.so %{buildroot}/usr/local/tsar/modules/
+install -p -D -m 0644 conf/tsar.cron %{buildroot}/etc/cron.d/tsar
+install -p -D -m 0644 conf/tsar.logrotate %{buildroot}/etc/logrotate.d/tsar
+install -p -D -m 0644 conf/tsar.8 %{buildroot}/usr/local/man/man8/tsar.8
+
+make -C lualib INSTALL_DIR=%{buildroot}/usr/local/tsar/lualib install
+
+make -C lualib INSTALL_DIR=%{buildroot}/usr/local/tsar/lualib install
+
+%clean
+[ "%{buildroot}" != "/" ] && %{__rm} -rf %{buildroot}
+
+
+%files
+%defattr(-,root,root)
+/usr/local/tsar/modules/*.so
+/usr/local/tsar/lualib
+
+%attr(755,root,root) /usr/bin/tsar
+%config(noreplace) /etc/tsar/tsar.conf
+%attr(644,root,root) /etc/cron.d/tsar
+%attr(644,root,root) /etc/logrotate.d/tsar
+%attr(644,root,root) /usr/local/man/man8/tsar.8
+
+%changelog
+* Sun Jan  6 2013 Ke Li <kongjian@taobao.com>
+- merge inner and opensource tsar
+* Thu Dec  9 2010 Ke Li <kongjian@taobao.com>
+- add logrotate for tsar.data
+* Mon Apr 26 2010 Bin Chen <kuotai@taobao.com>
+- first create tsar rpm package
diff --git a/rpm/tsar.spec.in b/rpm/tsar.spec.in
index 33f38cd..ba5ef5b 100644
--- a/rpm/tsar.spec.in
+++ b/rpm/tsar.spec.in
@@ -2,7 +2,7 @@ Name: tsar
 Version: _VERSION_
 Release: _RELEASE_
 Summary: Taobao System Activity Reporter
-URL: http://svn.simba.taobao.com/svn/cdn/trunk/tsar/Revision_SVN_REVISION
+URL: https://github.com/alibaba/tsar
 Group: Taobao/Common
 License: Commercial
 BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
@@ -13,12 +13,6 @@ tsar is Taobao monitor tool for collect system activity status, and report it.
 It have a plugin system that is easy for collect plugin development. and may
 setup different output target such as local logfile and remote nagios host.
 
-%package devel
-Summary: Taobao Tsar Devel
-Group: Taobao/Common
-%description devel
-devel package include tsar header files and module template for the development
-
 %prep
 %setup -q
 
@@ -31,7 +25,6 @@ rm -rf %{buildroot}
 mkdir -p %{buildroot}/usr/local/tsar/
 mkdir -p %{buildroot}/usr/local/tsar/modules/
 mkdir -p %{buildroot}/usr/local/tsar/conf/
-mkdir -p %{buildroot}/usr/local/tsar/devel/
 mkdir -p %{buildroot}/usr/local/man/man8/
 mkdir -p %{buildroot}/etc/logrotate.d/
 mkdir -p %{buildroot}/etc/tsar/
@@ -45,11 +38,14 @@ install -p -D -m 0644 conf/tsar.cron %{buildroot}/etc/cron.d/tsar
 install -p -D -m 0644 conf/tsar.logrotate %{buildroot}/etc/logrotate.d/tsar
 install -p -D -m 0644 conf/tsar.8 %{buildroot}/usr/local/man/man8/tsar.8
 
-install -p -D -m 0755 devel/tsardevel %{buildroot}/usr/bin/tsardevel
-install -p -D -m 0644 devel/mod_test.c %{buildroot}/usr/local/tsar/devel/mod_test.c
-install -p -D -m 0644 devel/mod_test.conf %{buildroot}/usr/local/tsar/devel/mod_test.conf
-install -p -D -m 0644 devel/Makefile.test %{buildroot}/usr/local/tsar/devel/Makefile.test
-install -p -D -m 0644 devel/tsar.h %{buildroot}/usr/local/tsar/devel/tsar.h
+make -C lualib INSTALL_DIR=%{buildroot}/usr/local/tsar/lualib install
+
+install -p -D -m 0755 luadevel/tsarluadevel %{buildroot}/usr/bin/tsarluadevel
+install -p -D -m 0644 luadevel/mod_lua_test.lua %{buildroot}/usr/local/tsar/luadevel/mod_lua_test.lua
+install -p -D -m 0644 luadevel/mod_lua_test.conf %{buildroot}/usr/local/tsar/luadevel/mod_lua_test.conf
+install -p -D -m 0644 luadevel/Makefile.test %{buildroot}/usr/local/tsar/luadevel/Makefile.test
+
+make -C lualib INSTALL_DIR=%{buildroot}/usr/local/tsar/lualib install
 
 %clean
 [ "%{buildroot}" != "/" ] && %{__rm} -rf %{buildroot}
@@ -58,25 +54,18 @@ install -p -D -m 0644 devel/tsar.h %{buildroot}/usr/local/tsar/devel/tsar.h
 %files
 %defattr(-,root,root)
 /usr/local/tsar/modules/*.so
+/usr/local/tsar/lualib
 
-%attr(755,root,root) %dir /usr/bin/tsar
+%attr(755,root,root) /usr/bin/tsar
 %config(noreplace) /etc/tsar/tsar.conf
-%attr(644,root,root) %dir /etc/cron.d/tsar
-%attr(644,root,root) %dir /etc/logrotate.d/tsar
-%attr(644,root,root) %dir /usr/local/man/man8/tsar.8
-
-%files devel
-%defattr(-,root,root)
-/usr/local/tsar/devel/tsar.h
-/usr/local/tsar/devel/Makefile.test
-/usr/local/tsar/devel/mod_test.c
-/usr/local/tsar/devel/mod_test.conf
-%attr(755,root,root) %dir /usr/bin/tsardevel
+%attr(644,root,root) /etc/cron.d/tsar
+%attr(644,root,root) /etc/logrotate.d/tsar
+%attr(644,root,root) /usr/local/man/man8/tsar.8
 
 %changelog
-* Wed Jan  6 2013 Ke Li <kongjian@taobao.com>
+* Sun Jan  6 2013 Ke Li <kongjian@taobao.com>
 - merge inner and opensource tsar
 * Thu Dec  9 2010 Ke Li <kongjian@taobao.com>
 - add logrotate for tsar.data
-* Tue Apr 26 2010 Bin Chen <kuotai@taobao.com>
+* Mon Apr 26 2010 Bin Chen <kuotai@taobao.com>
 - first create tsar rpm package
diff --git a/src/.gitignore b/src/.gitignore
new file mode 100644
index 0000000..b672fde
--- /dev/null
+++ b/src/.gitignore
@@ -0,0 +1 @@
+obj
diff --git a/src/Makefile b/src/Makefile
index a09c9ac..91df96e 100644
--- a/src/Makefile
+++ b/src/Makefile
@@ -1,15 +1,41 @@
-CFLAGS = -g -Wall
 CC = gcc
-INCLUDE_DIR = ../include
+SRC = tsar.c config.c debug.c framework.c output_file.c output_print.c output_db.c output_tcp.c output_nagios.c common.c tsar_lua_util.c
+OBJ = $(patsubst %.c, %.o,$(SRC))
+DEPS_DIR = deps
 
+BIN = tsar
+LUAJIT = $(notdir $(patsubst %.tar.gz,%,$(wildcard deps/LuaJIT*.tar.gz)))
 
-%.o: %.c
-	$(CC) -o $@ -c -I$(INCLUDE_DIR) $(CFLAGS) $<
+ODIR = obj
+DEPS = $(ODIR)/lib/libluajit-5.1.a
 
-all: tsar
+CFLAGS = -MD -g -O2 -Wall -I../include -I$(ODIR)/include
+LDFLAGS += -L$(ODIR)/lib -lluajit-5.1 -lm -ldl -rdynamic
 
-tsar: config.o debug.o framework.o tsar.o output_file.o output_print.o output_db.o output_nagios.o common.o
-	$(CC) config.o debug.o framework.o tsar.o output_file.o output_print.o output_db.o output_nagios.o common.o -o tsar -I$(INCLUDE_DIR) -g -Wall -ldl -rdynamic
+all: $(BIN)
+
+$(BIN): $(OBJ)
+	@echo LINK $(BIN)
+	$(CC) $^ -o tsar -I$(INCLUDE_DIR) $(CFLAGS) $(LDFLAGS)
+
+$(OBJ): $(DEPS) | $(ODIR)
+
+$(ODIR)/$(LUAJIT): $(DEPS_DIR)/$(LUAJIT).tar.gz | $(ODIR)
+	@tar -C $(ODIR) -xf $<
+
+$(ODIR)/lib/libluajit-5.1.a: $(ODIR)/$(LUAJIT) | $(ODIR)
+	@echo Building LuaJIT...
+	@$(MAKE) -C $< PREFIX=$(abspath $(ODIR)) BUILDMODE=static install
+
+$(ODIR)/%.o : %.c
+	@echo CC $<
+	@$(CC) $(CFLAGS) -c -o $@ $<
+
+$(ODIR):
+	@mkdir -p $@
 
 clean:
-	rm -rf *.o tsar
+	rm -rf *.o *.d $(BIN) $(ODIR);
+
+OBJS = *.o
+-include $(OBJS:.o=.d)
diff --git a/src/common.c b/src/common.c
index afa7dd2..8f03ed1 100644
--- a/src/common.c
+++ b/src/common.c
@@ -1,3 +1,4 @@
+
 /*
  * (C) 2010-2011 Alibaba Group Holding Limited
  *
@@ -15,233 +16,266 @@
  *
  */
 
+
 #include "tsar.h"
 
-int is_digit(char *str)
+
+int
+is_digit(const char *str)
 {
-	/*dont handle minus value in tsar.data */
-	//if(*str == '-')
-	//	str++;
-	while (*str) {
-		if (!isdigit(*str++))
-			return 0;
-	}
-	return 1;
+    if (*str == '-') {
+        str++;
+    }
+    /*dont handle minus value in tsar.data */
+    while (*str) {
+        if (!isdigit(*str++)) {
+            return 0;
+        }
+    }
+    return 1;
 }
 
 
 /*
  * convert record to array
  */
-int convert_record_to_array(U_64 *array, int l_array, char *record)
+int
+convert_record_to_array(U_64 *array, int l_array, const char *record)
 {
-	char *token;
-	char n_str[LEN_4096] = {0};
-	int i = 0;
-
-	if (!record || !strlen(record))
-		return 0;
-	memcpy(n_str, record, strlen(record));
-
-	token = strtok(n_str, DATA_SPLIT);
-	while (token) {
-		if (!is_digit(token))
-			return 0;
-		if(i < l_array)
-			*(array + i) = strtoull(token,NULL,10);
-		token = strtok(NULL, DATA_SPLIT);
-		i++;
-	}
-	if (i != l_array)
-		return 0;
-	return i;
+    int   i = 0;
+    char *ptr;
+    U_64  num;
+
+    if (l_array <= 0 || !record || !strlen(record)) {
+        return 0;
+    }
+
+    do {
+        num = strtoull(record, &ptr, 10);
+        array[i++] = num;
+        if (strpbrk(ptr, DATA_SPLIT) == NULL) break;
+        record = ptr + 1;
+    } while(i < l_array);
+
+    return i;
 }
 
 
-int merge_one_string(U_64 *array, int l_array, char *string, struct module *mod, int n_item)
+int
+merge_one_string(U_64 *array, int l_array, char *string, struct module *mod, int n_item)
 {
-	int i, len;
-	U_64 array_2[MAX_COL_NUM] = {0};
-	struct mod_info *info = mod->info;
-
-	if (!(len = convert_record_to_array(array_2, l_array, string)))
-		return 0;
-
-	for (i=0; i < len; i++) {
-		switch (info[i].merge_mode) {
-			case MERGE_SUM:
-				array[i] += array_2[i];
-				break;
-			case MERGE_AVG:
-				array[i] = (array[i] * (n_item - 1) + array_2[i])/n_item;
-				break;
-			default:
-				;	
-		}
-	}
-	return 1;
+    int    i, len;
+    U_64   array_2[MAX_COL_NUM] = {0};
+    struct mod_info *info = mod->info;
+
+    if ((len = convert_record_to_array(array_2, l_array, string)) <= 0) {
+        return 0;
+    }
+
+    for (i=0; i < len; i++) {
+        switch (info[i].merge_mode) {
+            case MERGE_SUM:
+                array[i] += array_2[i];
+                break;
+            case MERGE_AVG:
+                array[i] = (array[i] * (n_item - 1) + array_2[i]) / n_item;
+                break;
+            default:
+                ;
+        }
+    }
+    return 1;
 }
 
 
-int strtok_next_item(char item[], char *record, int *start)
+char*
+strtok_next_item(char *record, int *start)
 {
-	char *s_token, *e_token, *n_record;
-
-	if (!record || !strlen(record) || strlen(record) <= *start)
-		return 0;
-
-	n_record = record + *start;
-	e_token = strstr(n_record, ITEM_SPLIT);
-	if (!e_token)
-		return 0;
-	s_token = strstr(n_record, ITEM_SPSTART);
-	if (!s_token)
-		return 0;
-
-	memcpy(item, s_token + sizeof(ITEM_SPSTART) - 1, e_token - s_token - 1);
-	*start = e_token - record + sizeof(ITEM_SPLIT);
-	return 1;
+    char *s_token, *e_token, *n_record;
+
+    if (!record || !strlen(record) || strlen(record) <= *start) {
+        return NULL;
+    }
+
+    n_record = record + *start;
+    e_token = strpbrk(n_record, ITEM_SPLIT);
+    if (!e_token) {
+        return NULL;
+    }
+    s_token = strpbrk(n_record, ITEM_SPSTART);
+    if (!s_token) {
+        return NULL;
+    }
+    if (e_token < s_token) {
+        return NULL;
+    }
+
+    *start = e_token - record + 2;
+    return s_token + 1;
 }
 
 
-int merge_mult_item_to_array(U_64 *array, struct module *mod)
+int
+merge_mult_item_to_array(U_64 *array, struct module *mod)
 {
-	char item[LEN_128] = {0};
-	int pos = 0;
-	int n_item = 1;
-
-	memset(array, 0, sizeof(U_64) * mod->n_col);
-	while (strtok_next_item(item, mod->record, &pos)) {
-		if(!merge_one_string(array, mod->n_col, item, mod, n_item))
-			return 0;
-		n_item++;
-		memset(&item, 0, sizeof(item));
-	}
-	return 1;
+    int    pos = 0;
+    int    n_item = 1;
+    char  *item;
+
+    memset(array, 0, sizeof(U_64) * mod->n_col);
+    while ((item = strtok_next_item(mod->record, &pos)) != NULL) {
+        if (!merge_one_string(array, mod->n_col, item, mod, n_item)) {
+            return 0;
+        }
+        n_item++;
+    }
+    return 1;
 }
 
 
-int get_strtok_num(char *str, char *split)
+int
+get_strtok_num(const char *str, const char *split)
 {
-	int num = 0;
-	char *token, n_str[LEN_4096] = {0};
-
-	if (!str || !strlen(str))
-		return 0;
-
-	memcpy(n_str, str, strlen(str));
-	/* set print opt line */
-	token = strtok(n_str, split);
-	while (token) {
-		num++;
-		token = strtok(NULL, split);
-	}
-
-	return num;
+    int    num = 0;
+    char  *token, n_str[LEN_1M] = {0};
+
+    if (!str || !strlen(str)) {
+        return 0;
+    }
+
+    memcpy(n_str, str, strlen(str));
+    /* set print opt line */
+    token = strtok(n_str, split);
+    while (token) {
+        num++;
+        token = strtok(NULL, split);
+    }
+
+    return num;
 }
 
 
 /*
  * get__mod_hdr;  hdr format:HDR_SPLIT"hdr1"HDR_SLIT"hdr2"
  */
-void get_mod_hdr(char hdr[], struct module *mod)
+void
+get_mod_hdr(char hdr[], const struct module *mod)
 {
-	int i, pos = 0;
-	struct mod_info *info = mod->info;
-	for (i = 0; i < mod->n_col; i++) {
-		if(mod->spec) {
-			if(SPEC_BIT == info[i].summary_bit){
-				if (strlen(info[i].hdr) > 6) {
-					info[i].hdr[6] = '\0';
-				}
-				pos += sprintf(hdr + pos, "%s%s", info[i].hdr, PRINT_DATA_SPLIT);
-			}
-		}
-		else if (((DATA_SUMMARY == conf.print_mode) && (SUMMARY_BIT == info[i].summary_bit))
-				|| ((DATA_DETAIL == conf.print_mode) && (HIDE_BIT != info[i].summary_bit))) {
-			if (strlen(info[i].hdr) > 6) {
-				info[i].hdr[6] = '\0';
-			}
-			pos += sprintf(hdr + pos, "%s%s", info[i].hdr, PRINT_DATA_SPLIT);
-		}
-	}
+    int    i, pos = 0;
+    struct mod_info *info = mod->info;
+
+    for (i = 0; i < mod->n_col; i++) {
+        if (mod->spec) {
+            if (SPEC_BIT == info[i].summary_bit) {
+                if (strlen(info[i].hdr) > 6) {
+                    info[i].hdr[6] = '\0';
+                }
+                pos += sprintf(hdr + pos, "%s%s", info[i].hdr, PRINT_DATA_SPLIT);
+            }
+
+        } else {
+            if (((DATA_SUMMARY == conf.print_mode) && (SUMMARY_BIT == info[i].summary_bit))
+                || ((DATA_DETAIL == conf.print_mode) && (HIDE_BIT != info[i].summary_bit)))
+            {
+                if (strlen(info[i].hdr) > 6) {
+                    info[i].hdr[6] = '\0';
+                }
+                pos += sprintf(hdr + pos, "%s%s", info[i].hdr, PRINT_DATA_SPLIT);
+            }
+        }
+    }
 }
 
 
 /*
    get data from tsar.data
  */
-int get_st_array_from_file(int have_collect)
+int
+get_st_array_from_file(int have_collect)
 {
-	struct  module *mod;
-	int  i, ret;
-	char pre_line[LEN_10240] = {0};
-	char line[LEN_10240] = {0};
-	char detail[LEN_1024] = {0};
-	char pre_time[32] = {0};
-	char *s_token;
-	FILE *fp;
-
-	if (!have_collect)
-		collect_record(0);
-
-	/* update module parameter */
-	conf.print_merge = MERGE_ITEM;
-
-	sprintf(line, "%ld", statis.cur_time);
-	for (i = 0; i < statis.total_mod_num; i++) {
-		mod = &mods[i];
-		if (mod->enable && strlen(mod->record)) {
-			memset(&detail, 0, sizeof(detail));
-			/* save collect data to output_file */
-			sprintf(detail, "%s%s%s%s", SECTION_SPLIT, mod->opt_line, STRING_SPLIT, mod->record);
-			strcat(line, detail);
-		}
-	}
-
-	if (strlen(line))
-		strcat(line, "\n");
-
-	/* if fopen PRE_RECORD_FILE sucess then store data to pre_record */
-	if ((fp = fopen(PRE_RECORD_FILE, "r"))) {
-		if (!fgets(pre_line, LEN_10240, fp)) {
-			fclose(fp);
-			ret = -1;
-			goto out;
-		}
-	} else {
-		ret = -1;
-		goto out;
-	}
-
-	/* set print_interval */
-	s_token = strstr(pre_line, SECTION_SPLIT);
-	if (!s_token) {
-		ret = -1;
-		goto out;
-	}
-	memcpy(pre_time, pre_line, s_token - pre_line);
-	if (!(conf.print_interval = statis.cur_time - atol(pre_time)))
-		goto out;
-
-	/* read pre_line to mod->record and store to pre_array */
-	read_line_to_module_record(pre_line);
-	init_module_fields();
-	collect_record_stat();
-
-	/* read cur_line and stats operation */
-	read_line_to_module_record(line);
-	collect_record_stat();
-	ret = 0;
+    int         i, ret = 0;
+    char        detail[LEN_1M] = {0};
+    char        pre_time[32] = {0};
+    char       *s_token;
+    FILE       *fp;
+    struct      module *mod;
+    static char pre_line[LEN_10M] = {0};
+    static char line[LEN_10M] = {0};
+
+    if (!have_collect) {
+        collect_record(0);
+    }
+
+    /* update module parameter */
+    conf.print_merge = MERGE_ITEM;
+
+    sprintf(line, "%ld", statis.cur_time);
+    for (i = 0; i < statis.total_mod_num; i++) {
+        mod = mods[i];
+        if (mod->enable && strlen(mod->record)) {
+            memset(&detail, 0, sizeof(detail));
+            /* save collect data to output_file */
+            sprintf(detail, "%s%s%s%s", SECTION_SPLIT, mod->opt_line, STRING_SPLIT, mod->record);
+            strcat(line, detail);
+        }
+    }
+
+    if (strlen(line)) {
+        strcat(line, "\n");
+    }
+
+    /* if fopen PRE_RECORD_FILE sucess then store data to pre_record */
+    if ((fp = fopen(PRE_RECORD_FILE, "r"))) {
+        if (!fgets(pre_line, LEN_10M, fp)) {
+            if (fclose(fp) < 0) {
+                do_debug(LOG_FATAL, "fclose error:%s", strerror(errno));
+            }
+            ret = -1;
+            goto out;
+        } else {
+             if (fclose(fp) < 0) {
+                do_debug(LOG_FATAL, "fclose error:%s", strerror(errno));
+            }
+        }
+    } else {
+        ret = -1;
+        goto out;
+    }
+
+    /* set print_interval */
+    s_token = strpbrk(pre_line, SECTION_SPLIT);
+    if (!s_token) {
+        ret = -1;
+        goto out;
+    }
+    memcpy(pre_time, pre_line, s_token - pre_line);
+    if (!(conf.print_interval = statis.cur_time - atol(pre_time))) {
+        ret = -1;
+        goto out;
+    }
+
+    /* read pre_line to mod->record and store to pre_array */
+    read_line_to_module_record(pre_line);
+    init_module_fields();
+    collect_record_stat();
+
+    /* read cur_line and stats operation */
+    read_line_to_module_record(line);
+    collect_record_stat();
+    ret = 0;
 
 out:
-	/* store current record to PRE_RECORD_FILE */
-	if ((fp = fopen(PRE_RECORD_FILE, "w"))) {
-		strcat(line, "\n");
-		fputs(line, fp);
-		fclose(fp);
-		chmod(PRE_RECORD_FILE, 0666);
-	}
-
-	return ret;
+    /* store current record to PRE_RECORD_FILE */
+    if ((fp = fopen(PRE_RECORD_FILE, "w"))) {
+        strcat(line, "\n");
+        if (fputs(line, fp) < 0) {
+            do_debug(LOG_ERR, "fputs error:%s", strerror(errno));
+        }
+        if (fclose(fp) < 0) {
+            do_debug(LOG_FATAL, "fclose error:%s", strerror(errno));
+        }
+        chmod(PRE_RECORD_FILE, 0666);
+    }
+
+    return ret;
 }
diff --git a/src/config.c b/src/config.c
index 04861a1..7ff2c66 100644
--- a/src/config.c
+++ b/src/config.c
@@ -1,3 +1,4 @@
+
 /*
  * (C) 2010-2011 Alibaba Group Holding Limited
  *
@@ -15,293 +16,423 @@
  *
  */
 
+
 #include "tsar.h"
-//add mod to tsar
-void parse_mod(char *mod_name)
+
+
+/* add mod to tsar */
+void
+parse_mod(const char *mod_name)
 {
-	// check if the mod load already
-	int i = 0;
-	for ( i = 0; i < statis.total_mod_num; i++ )
-	{
-		struct module *mod = &mods[i];
-		if (!strcmp(mod->name,mod_name))
-			return;
-	}
-	struct module *mod = &mods[statis.total_mod_num++];
-	char	*token = strtok(NULL, W_SPACE);
-	if (token && (!strcasecmp(token, "on") || !strcasecmp(token, "enable"))) {
-		strncpy(mod->name, mod_name, strlen(mod_name));
-		token = strtok(NULL, W_SPACE);
-		if(token) {
-			strncpy(mod->parameter, token, strlen(token));
-		}
-		return;
-	}
-	else {
-		memset(mod, 0, sizeof(struct module));
-		statis.total_mod_num--;
-	}
+    int     i;
+    struct  module *mod;
+    char   *token;
+
+    token = strtok(NULL, W_SPACE);
+    if (token && strcasecmp(token, "on") && strcasecmp(token, "enable")) {
+        return;
+    }
+
+    /* check if the mod load already */
+    for ( i = 0; i < statis.total_mod_num; i++ )
+    {
+        mod = mods[i];
+        if (!strcmp(mod->name, mod_name)) {
+            return;
+        }
+    }
+    if (statis.total_mod_num >= MAX_MOD_NUM) {
+        do_debug(LOG_ERR, "Max mod number is %d ignore mod %s\n", MAX_MOD_NUM, mod_name);
+        return;
+    }
+    mod = mods[statis.total_mod_num++] = malloc(sizeof(struct module));
+    if (mod == NULL) {
+        do_debug(LOG_ERR, "Failed to alloc memory for mod %s\n", mod_name);
+        return;
+    }
+    memset(mod, '\0', sizeof(struct module));
+
+    strncpy(mod->name, mod_name, LEN_32);
+    token = strtok(NULL, W_SPACE);
+    if (token) {
+        size_t p = strlen(token);
+        if (p < LEN_256) {
+            strncpy(mod->parameter, token, p);
+        } else {
+            p = 0;
+        }
+
+        /*if exist more parameters, add them */
+        while((token = strtok(NULL, W_SPACE)) != NULL) {
+            size_t l = strlen(token);
+            if (p + l + 1 >= LEN_256) {
+                break;
+            }
+            mod->parameter[p++] = ' ';
+            strncpy(mod->parameter + p, token, l);
+            p += l;
+        }
+        mod->parameter[p] = '\0';
+    }
 }
 
-void special_mod(char *spec_mod)
+void
+special_mod(const char *spec_mod)
 {
-	int i = 0, j = 0;
-	char mod_name[32];
-	struct module *mod = NULL;
-	memset(mod_name,0,LEN_32);
-	sprintf(mod_name,"mod_%s",spec_mod+5);
-	for ( i = 0; i < statis.total_mod_num; i++ )
-	{
-		mod = &mods[i];
-		if (!strcmp(mod->name,mod_name)) {
-			/* set special field */
-			load_modules();
-			char    *token = strtok(NULL, W_SPACE);
-			struct mod_info *info = mod->info;
-			for (j=0; j < mod->n_col; j++) {
-				char *p = info[j].hdr;
-				while( *p  == ' ') p++;
-				if(strstr(token,p)){
-					info[j].summary_bit = SPEC_BIT;
-					mod->spec = 1;
-				}
-			}
-		}
-	}
+    int       i = 0, j = 0;
+    char      mod_name[LEN_32];
+    struct    module *mod = NULL;
+
+    memset(mod_name, 0, LEN_32);
+    sprintf(mod_name, "mod_%s", spec_mod + 5);
+    for ( i = 0; i < statis.total_mod_num; i++ )
+    {
+        mod = mods[i];
+        if (!strcmp(mod->name, mod_name)) {
+            /* set special field */
+            load_modules();
+            char    *token = strtok(NULL, W_SPACE);
+            struct mod_info *info = mod->info;
+            for (j=0; j < mod->n_col; j++) {
+                char *p = info[j].hdr;
+                while (*p  == ' ') {
+                    p++;
+                }
+                if (strstr(token, p)) {
+                    info[j].summary_bit = SPEC_BIT;
+                    mod->spec = 1;
+                }
+            }
+        }
+    }
 }
 
-void parse_int(int *var)
+void
+parse_int(int *var)
 {
-	char	*token = strtok(NULL, W_SPACE);
-	if (token == NULL)
-		do_debug(LOG_FATAL, "Bungled line");
-	*var = strtol(token,NULL,0);
+    char   *token = strtok(NULL, W_SPACE);
+
+    if (token == NULL) {
+        do_debug(LOG_FATAL, "Bungled line");
+    }
+    *var = strtol(token, NULL, 0);
 }
 
-void parse_string(char *var)
+void
+parse_string(char *var)
 {
-	char    *token = strtok(NULL, W_SPACE);
+    char   *token = strtok(NULL, W_SPACE);
 
-	if (token)
-		strncpy(var, token, strlen(token));
+    if (token != NULL && var != NULL) {
+        strncpy(var, token, strlen(token));
+    }
 }
 
-void parse_add_string(char *var)
+void
+parse_add_string(char *var)
 {
-	char    *token = strtok(NULL, W_SPACE);
-	if (var == NULL){
-		if(token)
-			strncpy(var, token, strlen(token));
-	}else{
-		if(token){
-			strcat(token, ",");
-			strncat(token, var, strlen(var));
-		}
-		if(token)
-			strncpy(var, token, strlen(token));
-	}
+    char   *token = strtok(NULL, W_SPACE);
+
+    if (token != NULL && var != NULL) {
+        if (var[0] != '\0') {
+            strcat(var, ",");
+        }
+        strncat(var, token, strlen(token));
+    }
 }
 
-void set_debug_level()
+void
+set_debug_level()
 {
-	char    *token = strtok(NULL, W_SPACE);
-	if(token){
-		if (!strcmp(token,"INFO"))
-			conf.debug_level = LOG_INFO;
-		else if (!strcmp(token,"WARN"))
-			conf.debug_level = LOG_WARN;
-		else if (!strcmp(token,"DEBUG"))
-			conf.debug_level = LOG_DEBUG;
-		else if (!strcmp(token,"ERROR"))
-			conf.debug_level = LOG_ERR;
-		else if (!strcmp(token,"FATAL"))
-			conf.debug_level = LOG_FATAL;
-		else
-			conf.debug_level = LOG_ERR;
-	}
+    char   *token = strtok(NULL, W_SPACE);
+
+    if (token) {
+        if (!strcmp(token, "INFO")) {
+            conf.debug_level = LOG_INFO;
+
+        } else if (!strcmp(token, "WARN")) {
+            conf.debug_level = LOG_WARN;
+
+        } else if (!strcmp(token, "DEBUG")) {
+            conf.debug_level = LOG_DEBUG;
+
+        } else if (!strcmp(token, "ERROR")) {
+            conf.debug_level = LOG_ERR;
+
+        } else if (!strcmp(token, "FATAL")) {
+            conf.debug_level = LOG_FATAL;
+
+        } else {
+            conf.debug_level = LOG_ERR;
+        }
+    }
 }
 
 /* parse every config line */
-static int parse_line(char *buff)
+static int
+parse_line(char *buff)
+{
+    char   *token;
+    int     i;
+
+    if ((token = strtok(buff, W_SPACE)) == NULL) {
+        /* ignore empty lines */
+        (void) 0;
+
+    } else if (token[0] == '#') {
+        /* ignore comment lines */
+        (void) 0;
+
+    } else if (strstr(token, "mod_")) {
+        parse_mod(token);
+
+    } else if (strstr(token, "spec_")) {
+        special_mod(token);
+
+    } else if (!strcmp(token, "output_interface")) {
+        parse_string(conf.output_interface);
+
+    } else if (!strcmp(token, "output_file_path")) {
+        parse_string(conf.output_file_path);
+
+    } else if (!strcmp(token, "output_db_addr")) {
+        parse_string(conf.output_db_addr);
+
+    } else if (!strcmp(token, "output_db_mod")) {
+        parse_add_string(conf.output_db_mod);
+
+    } else if (!strcmp(token, "output_tcp_mod")) {
+        parse_add_string(conf.output_tcp_mod);
+    } else if (!strcmp(token, "output_tcp_addr")) {
+        for(i = 0; i < MAX_TCP_ADDR_NUM; i++){
+            parse_string(conf.output_tcp_addr[i]);
+            if(conf.output_tcp_addr[i][0] != 0){
+                conf.output_tcp_addr_num++;
+            } else {
+                break;
+            }
+        }
+    } else if (!strcmp(token, "output_tcp_merge")) {
+        parse_string(conf.output_tcp_merge);
+
+    } else if (!strcmp(token, "output_nagios_mod")) {
+        parse_add_string(conf.output_nagios_mod);
+
+    } else if (!strcmp(token, "output_stdio_mod")) {
+        parse_add_string(conf.output_stdio_mod);
+
+    } else if (!strcmp(token, "debug_level")) {
+        set_debug_level();
+
+    } else if (!strcmp(token, "include")) {
+        get_include_conf();
+
+    } else if (!strcmp(token, "server_addr")) {
+        parse_string(conf.server_addr);
+
+    } else if (!strcmp(token, "server_port")) {
+        parse_int(&conf.server_port);
+
+    } else if (!strcmp(token, "cycle_time")) {
+        parse_int(&conf.cycle_time);
+
+    } else if (!strcmp(token, "max_day")) {
+        parse_int(&conf.print_max_day);
+
+    } else if (!strcmp(token, "send_nsca_cmd")) {
+        parse_string(conf.send_nsca_cmd);
+
+    } else if (!strcmp(token, "send_nsca_conf")) {
+        parse_string(conf.send_nsca_conf);
+
+    } else if (!strcmp(token, "threshold")) {
+        get_threshold();
+
+    } else if (!strcmp(token, "lua_package_path")) {
+        parse_string(conf.lua_path);
+
+    } else if (!strcmp(token, "lua_package_cpath")) {
+        parse_string(conf.lua_cpath);
+
+    } else {
+        return 0;
+    }
+    return 1;
+}
+
+static void
+process_input_line(char *config_input_line, int len, const char *file_name)
 {
-	char    *token;
-
-	if ((token = strtok(buff, W_SPACE)) == NULL)
-		(void) 0;       /* ignore empty lines */
-	else if (strstr(token, "mod_"))
-		parse_mod(token);
-	else if (strstr(token, "spec_"))
-		special_mod(token);
-	else if (!strcmp(token, "output_interface"))
-		parse_string(conf.output_interface);
-	else if (!strcmp(token, "output_file_path"))
-		parse_string(conf.output_file_path);
-	else if (!strcmp(token, "output_db_addr"))
-		parse_string(conf.output_db_addr);
-	else if (!strcmp(token, "output_db_mod"))
-		parse_add_string(conf.output_db_mod);
-	else if (!strcmp(token, "output_nagios_mod"))
-		parse_add_string(conf.output_nagios_mod);
-	else if (!strcmp(token, "output_stdio_mod"))
-		parse_add_string(conf.output_stdio_mod);
-	else if (!strcmp(token, "debug_level"))
-		set_debug_level();
-	else if (!strcmp(token, "include"))
-		get_include_conf();
-	else if (!strcmp(token, "server_addr"))
-		parse_string(conf.server_addr);
-	else if (!strcmp(token, "server_port"))
-		parse_int(conf.server_port);
-	else if (!strcmp(token, "cycle_time"))
-		parse_int(conf.cycle_time);
-	else if (!strcmp(token, "send_nsca_cmd"))
-		parse_string(conf.send_nsca_cmd);
-	else if (!strcmp(token, "send_nsca_conf"))
-		parse_string(conf.send_nsca_conf);
-	else if (!strcmp(token, "threshold"))
-		get_threshold();
-	else
-		return 0;
-	return 1;
+    char *token;
+
+    if ((token = strchr(config_input_line, '\n'))) {
+        *token = '\0';
+    }
+    if ((token = strchr(config_input_line, '\r'))) {
+        *token = '\0';
+    }
+    if (config_input_line[0] == '#') {
+        goto final;
+    } else if (config_input_line[0] == '\0') {
+        goto final;
+    }
+    /* FIXME can't support wrap line */
+    if (!parse_line(config_input_line)) {
+        do_debug(LOG_INFO, "parse_config_file: unknown keyword in '%s' at file %s\n",
+                 config_input_line, file_name);
+    }
+
+final:
+    memset(config_input_line, '\0', len);
 }
 
-void parse_config_file(const char *file_name)
+void
+parse_config_file(const char *file_name)
 {
-	FILE    *fp;
-	char    *token;
-	char    config_input_line[LEN_1024] = {0};
-
-	if (!(fp = fopen(file_name, "r"))) {
-		do_debug(LOG_FATAL, "Unable to open configuration file: %s", file_name);
-	}
-
-	memset(&mods, '\0', sizeof(mods));
-	memset(&conf, '\0', sizeof(conf));
-	memset(&statis, '\0', sizeof(statis));
-	conf.server_port = (int *)malloc(sizeof(int));
-	conf.cycle_time = (int *)malloc(sizeof(int));
-	conf.debug_level = LOG_ERR;
-	conf.print_detail = FALSE;
-	while (fgets(config_input_line, LEN_1024, fp)) {
-		if ((token = strchr(config_input_line, '\n')))
-			*token = '\0';
-		if ((token = strchr(config_input_line, '\r')))
-			*token = '\0';
-		if (config_input_line[0] == '#') {
-			memset(config_input_line, '\0', LEN_1024);
-			continue;
-		}
-		if (config_input_line[0] == '\0')
-			continue;
-		//FIXME can't supprot wrap line
-		if (!parse_line(config_input_line)) {
-			do_debug(LOG_INFO, "parse_config_file: unknown keyword in '%s' \n", config_input_line);
-		}
-		memset(config_input_line, '\0', LEN_1024);
-	}
-	fclose(fp);
+    FILE   *fp;
+    char    config_input_line[LEN_1024] = {0};
+
+    if (!(fp = fopen(file_name, "r"))) {
+        do_debug(LOG_FATAL, "Unable to open configuration file: %s", file_name);
+    }
+
+    memset(&conf, '\0', sizeof(conf));
+    memset(&statis, '\0', sizeof(statis));
+    conf.debug_level = LOG_ERR;
+    conf.print_detail = FALSE;
+    conf.print_max_day = 365;
+    sprintf(conf.output_interface, "file");
+    while (fgets(config_input_line, LEN_1024, fp)) {
+        process_input_line(config_input_line, LEN_1024, file_name);
+    }
+    if (fclose(fp) < 0) {
+        do_debug(LOG_FATAL, "fclose error:%s", strerror(errno));
+    }
 }
-//deal with the include statment
-void get_include_conf()
+
+/* deal with the include statment */
+void
+get_include_conf()
 {
-	char *token = strtok(NULL, W_SPACE);
-	char *tmp,*p;
-	FILE *stream, *fp;
-	char cmd[LEN_1024] = {0};
-	char buf[LEN_1024] = {0};
-	char config_input_line[LEN_1024] = {0};
-	if(token){
-		memset(cmd, '\0', LEN_1024);
-		sprintf(cmd,"ls %s 2>/dev/null",token);
-		if(strchr(cmd,';') != NULL || strchr(cmd,'|') != NULL || strchr(cmd,'&') != NULL)
-			do_debug(LOG_ERR,"include formart Error:%s\n",cmd);
-		stream = popen(cmd, "r");
-		if(stream == NULL){
-			do_debug(LOG_ERR,"popen failed. Error:%s\n",strerror(errno));
-			return;
-		}
-		memset(buf, '\0', LEN_1024);
-		while (fgets(buf, LEN_1024, stream)) {
-			do_debug(LOG_INFO, "parse file %s", buf);
-			p = buf;
-			while(p){
-				if(*p == '\r' || *p == '\n'){
-					*p = '\0';
-					break;
-				}
-				p++;
-			}
-			if (!(fp = fopen(buf, "r"))) {
-				do_debug(LOG_ERR, "Unable to open configuration file: %s Error msg: %s\n", buf, strerror(errno));
-				continue;
-			}
-			memset(config_input_line, '\0', LEN_1024);
-			while (fgets(config_input_line, LEN_1024, fp)) {
-				if ((tmp = strchr(config_input_line, '\n')))
-					*tmp= '\0';
-				if ((tmp = strchr(config_input_line, '\r')))
-					*tmp = '\0';
-				if (config_input_line[0] == '#') {
-					memset(config_input_line, '\0', LEN_1024);
-					continue;
-				}
-				if (config_input_line[0] == '\0')
-					continue;
-				//FIXME can't supprot wrap line
-				if (!parse_line(config_input_line)) {
-					do_debug(LOG_INFO, "parse_config_file: unknown keyword in '%s' at file %s\n", config_input_line, buf);
-				}
-				memset(config_input_line, '\0', LEN_1024);
-			}
-			fclose(fp);
-		}
-		if(pclose(stream) == -1)
-			do_debug(LOG_WARN,"pclose error\n");
-	}
+    char   *token = strtok(NULL, W_SPACE);
+    char   *p;
+    FILE   *stream, *fp;
+    char    cmd[LEN_1024] = {0};
+    char    buf[LEN_1024] = {0};
+    char    config_input_line[LEN_1024] = {0};
+
+    if (token) {
+        memset(cmd, '\0', LEN_1024);
+        sprintf(cmd, "ls %s 2>/dev/null", token);
+        if (strchr(cmd, ';') != NULL || strchr(cmd, '|') != NULL || strchr(cmd, '&') != NULL) {
+            do_debug(LOG_ERR, "include formart Error:%s\n", cmd);
+        }
+        stream = popen(cmd, "r");
+        if (stream == NULL) {
+            do_debug(LOG_ERR, "popen failed. Error:%s\n", strerror(errno));
+            return;
+        }
+        memset(buf, '\0', LEN_1024);
+        while (fgets(buf, LEN_1024, stream)) {
+            do_debug(LOG_INFO, "parse file %s", buf);
+            p = buf;
+            while (p) {
+                if (*p == '\r' || *p == '\n') {
+                    *p = '\0';
+                    break;
+                }
+                p++;
+            }
+            if (!(fp = fopen(buf, "r"))) {
+                do_debug(LOG_ERR, "Unable to open configuration file: %s Error msg: %s\n", buf, strerror(errno));
+                continue;
+            }
+            memset(config_input_line, '\0', LEN_1024);
+            while (fgets(config_input_line, LEN_1024, fp)) {
+                process_input_line(config_input_line, LEN_1024, buf);
+            }
+            if (fclose(fp) < 0) {
+                do_debug(LOG_FATAL, "fclose error:%s", strerror(errno));
+            }
+        }
+        if (pclose(stream) == -1)
+            do_debug(LOG_WARN, "pclose error\n");
+    }
 }
-// get nagios alert threshold value
-void get_threshold(){
-	/* set nagios value */
-	char *token = strtok(NULL, W_SPACE);
-	char tmp[4][LEN_32];
-	if ( conf.mod_num >= MAX_MOD_NUM) {
-		do_debug(LOG_FATAL, "Too many mod threshold\n");
-	}
-	sscanf(token,"%[^;];%[.N0-9];%[.N0-9];%[.N0-9];%[.N0-9];",conf.check_name[conf.mod_num],tmp[0],tmp[1],tmp[2],tmp[3]);
-	if(!strcmp(tmp[0],"N"))
-		conf.wmin[conf.mod_num]=0;
-	else
-		conf.wmin[conf.mod_num]=atof(tmp[0]);
-	if(!strcmp(tmp[1],"N"))
-		conf.wmax[conf.mod_num]=0;
-	else
-		conf.wmax[conf.mod_num]=atof(tmp[1]);
-	if(!strcmp(tmp[2],"N"))
-		conf.cmin[conf.mod_num]=0;
-	else
-		conf.cmin[conf.mod_num]=atof(tmp[2]);
-	if(!strcmp(tmp[3],"N"))
-		conf.cmax[conf.mod_num]=0;
-	else
-		conf.cmax[conf.mod_num]=atof(tmp[3]);
-	conf.mod_num++;
+
+/* get nagios alert threshold value */
+void
+get_threshold()
+{
+    /* set nagios value */
+    char   *token = strtok(NULL, W_SPACE);
+    char    tmp[4][LEN_32];
+
+    if (conf.mod_num >= MAX_MOD_NUM) {
+        do_debug(LOG_FATAL, "Too many mod threshold\n");
+    }
+    sscanf(token, "%[^;];%[.N0-9];%[.N0-9];%[.N0-9];%[.N0-9];",
+           conf.check_name[conf.mod_num], tmp[0], tmp[1], tmp[2], tmp[3]);
+
+    if (!strcmp(tmp[0], "N")) {
+        conf.wmin[conf.mod_num] = 0;
+
+    } else {
+        conf.wmin[conf.mod_num] = atof(tmp[0]);
+    }
+    if (!strcmp(tmp[1], "N")) {
+        conf.wmax[conf.mod_num] = 0;
+
+    } else {
+        conf.wmax[conf.mod_num] = atof(tmp[1]);
+    }
+    if (!strcmp(tmp[2], "N")) {
+        conf.cmin[conf.mod_num] = 0;
+
+    } else {
+        conf.cmin[conf.mod_num]=atof(tmp[2]);
+    }
+    if (!strcmp(tmp[3], "N")) {
+        conf.cmax[conf.mod_num] = 0;
+
+    } else {
+        conf.cmax[conf.mod_num] = atof(tmp[3]);
+    }
+    conf.mod_num++;
 }
 
-void set_special_field(char *s)
+void
+set_special_field(const char *s)
 {
-	int i = 0, j = 0;
-	struct module *mod = NULL;
-	for ( i = 0; i < statis.total_mod_num; i++ )
-	{
-		mod = &mods[i];
-		struct mod_info *info = mod->info;
-		for (j=0; j < mod->n_col; j++) {
-			char *p = info[j].hdr;
-			while( *p  == ' ') p++;
-			if(strstr(s,p)){
-				info[j].summary_bit = SPEC_BIT;
-				mod->spec = 1;
-			}
-		}
-	}
+    int    i = 0, j = 0;
+    struct module *mod = NULL;
+
+    for (i = 0; i < statis.total_mod_num; i++)
+    {
+        mod = mods[i];
+        struct mod_info *info = mod->info;
+        for (j=0; j < mod->n_col; j++) {
+            char *p = info[j].hdr;
+            while (*p  == ' ') {
+                p++;
+            }
+            if (strstr(s, p)) {
+                info[j].summary_bit = SPEC_BIT;
+                mod->spec = 1;
+            }
+        }
+    }
+}
+
+void
+set_special_item(const char *s)
+{
+    int    i = 0;
+    struct module *mod = NULL;
+
+    for (i = 0; i < statis.total_mod_num; i++)
+    {
+        mod = mods[i];
+        strncpy(mod->print_item, s, LEN_256);
+    }
 }
diff --git a/src/debug.c b/src/debug.c
index a694480..d7d8be7 100644
--- a/src/debug.c
+++ b/src/debug.c
@@ -1,3 +1,4 @@
+
 /*
  * (C) 2010-2011 Alibaba Group Holding Limited
  *
@@ -15,22 +16,36 @@
  *
  */
 
+
 #include "tsar.h"
 
-void do_debug(log_level_t level, const char *fmt, ...)
+
+void
+_do_debug(log_level_t level, const char *file, int line, const char *fmt, ...)
 {
-	//FIXME
-	if (level >= conf.debug_level) {
-		va_list	argp;
-		time_t	timep;
-
-		time(&timep);
-		va_start(argp, fmt);
-		vfprintf(stderr, fmt, argp);
-		fflush(stderr);
-		va_end(argp);
-	}
-
-	if (level == LOG_FATAL)
-		exit(1);
+    char      *timestr;
+    time_t     timep;
+    va_list    argp;
+    struct tm *local;
+
+    /* FIXME */
+    if (level >= conf.debug_level) {
+
+        time(&timep);
+        local = localtime(&timep);
+        timestr = asctime(local);
+
+        fprintf(stderr, "[%.*s] %s:%d ", 
+                (int)(strlen(timestr) - 1), timestr, file, line);
+
+        va_start(argp, fmt);
+        vfprintf(stderr, fmt, argp);
+        fflush(stderr);
+        va_end(argp);
+    }
+
+    if (level == LOG_FATAL) {
+        fprintf(stderr, "\n");
+        exit(1);
+    }
 }
diff --git a/src/deps/LuaJIT-2.0.4.tar.gz b/src/deps/LuaJIT-2.0.4.tar.gz
new file mode 100644
index 0000000..0713a5d
Binary files /dev/null and b/src/deps/LuaJIT-2.0.4.tar.gz differ
diff --git a/src/framework.c b/src/framework.c
index f045d63..c5ddb04 100644
--- a/src/framework.c
+++ b/src/framework.c
@@ -1,3 +1,4 @@
+
 /*
  * (C) 2010-2011 Alibaba Group Holding Limited
  *
@@ -15,446 +16,522 @@
  *
  */
 
+
 #include "tsar.h"
 
-void register_mod_fileds(struct module *mod, char *opt, char *usage,
-		struct mod_info *info, int n_col, void *data_collect, void *set_st_record)
-{
-	sprintf(mod->opt_line, "%s", opt);
-	sprintf(mod->usage, "%s", usage);
-	mod->info = info;
-	mod->n_col = n_col;
-	mod->data_collect = data_collect;
-	mod->set_st_record = set_st_record;
-}
 
 
-void set_mod_record(struct module *mod, char *record)
+void
+register_mod_fields(struct module *mod, const char *opt, const char *usage,
+    struct mod_info *info, int n_col, void *data_collect, void *set_st_record)
 {
-	if (record)
-		sprintf(mod->record, "%s", record);
+    sprintf(mod->opt_line, "%s", opt);
+    sprintf(mod->usage, "%s", usage);
+    mod->info = info;
+    mod->n_col = n_col;
+    mod->data_collect = data_collect;
+    mod->set_st_record = set_st_record;
 }
 
 
-/* 
- * load module from dir 
- */
-void load_modules()
+void
+set_mod_record(struct module *mod, const char *record)
 {
-	char	buff[LEN_128] = {0};
-	char	mod_path[LEN_128] = {0};
-	struct	module *mod = NULL;
-	int	(*mod_register)(struct module *);
-	int	i;
-
-	/* get the full path of modules */
-	sprintf(buff, "/usr/local/tsar/modules");
-
-	for (i = 0; i < statis.total_mod_num; i++) {
-		mod = &mods[i];
-		if (!mod->lib) {
-			memset(mod_path, '\0', LEN_128);
-			snprintf(mod_path, LEN_128, "%s/%s.so", buff, mod->name);
-			if (!(mod->lib = dlopen(mod_path, RTLD_NOW|RTLD_GLOBAL))) {
-				do_debug(LOG_ERR, "load_modules: dlopen module %s err %s\n", mod->name, dlerror());
-			}
-			else {
-				mod_register = dlsym(mod->lib, "mod_register");
-				if (dlerror()) {
-					do_debug(LOG_ERR, "load_modules: dlsym module %s err %s\n", mod->name, dlerror());
-					break;
-				}
-				else {
-					mod_register(mod);
-					mod->enable = 1;
-					mod->spec = 0;
-					do_debug(LOG_INFO, "load_modules: load new module '%s' to mods\n", mod_path);
-				}
-			}
-		}
-	}
+    if (record) {
+        sprintf(mod->record, "%s", record);
+    }
 }
 
 
 /*
- * module name must be composed by alpha/number/_
- * match return 1
+ * load module from dir
  */
-int is_include_string(char *mods, char *mod)
+void
+load_modules()
 {
-	char *token, n_str[LEN_512] = {0};
-
-	memcpy(n_str, mods, strlen(mods));
-
-	token = strtok(n_str, DATA_SPLIT);
-	while (token) {
-		if (!strcmp(token, mod)) {
-			return 1;
-		}
-		token = strtok(NULL, DATA_SPLIT);
-	}
-	return 0;
+    int     i;
+    char    buff[LEN_128] = {0};
+    char    mod_path[LEN_128] = {0};
+    struct  module *mod = NULL;
+    int    (*mod_register) (struct module *);
+
+    /* get the full path of modules */
+    sprintf(buff, DEFAULT_MODULE_PATH);
+
+    for (i = 0; i < statis.total_mod_num; i++) {
+        mod = mods[i];
+
+        if (strlen(mod->name) == 0) {
+            continue;
+        }
+
+        if (strncmp(MOD_LUA_PREFIX, mod->name, strlen(MOD_LUA_PREFIX)) == 0) {
+            do_debug(LOG_DEBUG, "load_modules: ready to load %s\n", mod->name);
+            load_lua_module(L, mod);
+            continue;
+        }
+
+        if (!mod->lib) {
+            snprintf(mod_path, LEN_128, "%s/%s.so", buff, mod->name);
+            if (!(mod->lib = dlopen(mod_path, RTLD_NOW|RTLD_GLOBAL))) {
+                do_debug(LOG_ERR, "load_modules: dlopen module %s err %s\n", mod->name, dlerror());
+
+            } else {
+                mod_register = dlsym(mod->lib, "mod_register");
+                if (dlerror()) {
+                    do_debug(LOG_ERR, "load_modules: dlsym module %s err %s\n", mod->name, dlerror());
+                    break;
+
+                } else {
+                    mod_register(mod);
+                    mod->enable = 1;
+                    mod->spec = 0;
+                    do_debug(LOG_INFO, "load_modules: load new module '%s' to mods\n", mod_path);
+                }
+            }
+        }
+    }
 }
 
 
 /*
- * reload modules by mods, if not find in mods, then set module disable 
+ * reload modules by mods, if not find in mods, then set module disable
+ * return 1 if mod load ok
+ * return 0 else
  */
-//如果有模块被成功reload 返回1 否则返回0
-int reload_modules(char *s_mod)
+int
+reload_modules(const char *s_mod)
 {
-	int	i;
-	int reload = 0;
-	struct	module *mod;
-
-	if (!s_mod || !strlen(s_mod))
-		return reload;
-
-	for (i = 0; i < statis.total_mod_num; i++) {
-		mod = &mods[i];
-		if (is_include_string(s_mod, mod->name) || is_include_string(s_mod, mod->opt_line)) {
-			mod->enable = 1;
-			reload = 1;
-		} else
-			mod->enable = 0;
-	}
-	return reload;
+    int    i;
+    int    reload = 0;
+    char   buf[LEN_512], name[LEN_64], *token, *param;
+
+    if (!s_mod || !strlen(s_mod)) {
+        return reload;
+    }
+
+    strncpy(buf, s_mod, strlen(s_mod) + 1);
+
+    for (i = 0; i < statis.total_mod_num; i++)
+        mods[i]->enable = 0;
+
+    token = strtok(buf, DATA_SPLIT);
+    while (token != NULL) {
+        strncpy(name, token, strlen(token) + 1);
+
+        /* extract the parameter specified in the command line */
+        param = strchr(name, PARAM_SPLIT);
+        if (param != NULL) {
+            *param = '\0';
+            ++param;
+        }
+
+        for (i = 0; i < statis.total_mod_num; i++) {
+            if (strcmp(name, mods[i]->name) == 0
+                    || strcmp(name, mods[i]->opt_line) == 0) {
+                reload = 1;
+                mods[i]->enable = 1;
+
+                if (param != NULL) {
+                    strncpy(mods[i]->parameter, param, strlen(param) + 1);
+                }
+
+                break;
+            }
+        }
+
+        token = strtok(NULL, DATA_SPLIT);
+    }
+
+    return reload;
 }
 
 #ifdef OLDTSAR
 /*
- * reload check modules by mods, if not find in mods, then set module disable 
+ * reload check modules by mods, if not find in mods, then set module disable
  */
-void reload_check_modules()
+void
+reload_check_modules()
 {
-	int     i;  
-	struct  module *mod;
-
-	for (i = 0; i < statis.total_mod_num; i++) {
-		mod = &mods[i];
-		if (!strcmp(mod->name,"mod_apache") || !strcmp(mod->name,"mod_cpu") || !strcmp(mod->name,"mod_mem") || !strcmp(mod->name,"mod_load") || !strcmp(mod->name,"mod_partition") || !strcmp(mod->name,"mod_io") || !strcmp(mod->name,"mod_tcp") || !strcmp(mod->name,"mod_traffic") || !strcmp(mod->name,"mod_nginx")) {
-			mod->enable = 1;
-		} else
-			mod->enable = 0;
-	}   
+    int    i;
+    struct module *mod;
+
+    for (i = 0; i < statis.total_mod_num; i++) {
+        mod = mods[i];
+        if (!strcmp(mod->name, "mod_apache")
+             || !strcmp(mod->name, "mod_cpu")
+             || !strcmp(mod->name, "mod_mem")
+             || !strcmp(mod->name, "mod_load")
+             || !strcmp(mod->name, "mod_partition")
+             || !strcmp(mod->name, "mod_io")
+             || !strcmp(mod->name, "mod_tcp")
+             || !strcmp(mod->name, "mod_traffic")
+             || !strcmp(mod->name, "mod_nginx")
+             || !strcmp(mod->name, "mod_swap"))
+        {
+            mod->enable = 1;
+
+        } else {
+            mod->enable = 0;
+        }
+    }
 }
 /*end*/
 #endif
 
-/* 
+/*
  * 1. alloc or realloc store array
  * 2. set mod->n_item
  */
-void init_module_fields()
+void
+init_module_fields()
 {
-	struct module *mod = NULL;
-	int  i;
-
-	for (i = 0; i < statis.total_mod_num; i++) {
-		mod = &mods[i];
-		if (!mod->enable)	
-			continue;
-
-		if (MERGE_ITEM == conf.print_merge)
-			mod->n_item = 1;
-		else 
-			/* get mod->n_item first, and mod->n_item will be reseted in reading next line */
-			mod->n_item = get_strtok_num(mod->record, ITEM_SPLIT);
-
-		if (mod->n_item) {
-			mod->pre_array = (U_64 *)calloc(mod->n_item * mod->n_col, sizeof(U_64));
-			mod->cur_array = (U_64 *)calloc(mod->n_item * mod->n_col, sizeof(U_64));
-			mod->st_array = (double *)calloc(mod->n_item * mod->n_col, sizeof(double));
-			if (conf.print_tail) {
-				mod->max_array = (double *)calloc(mod->n_item * mod->n_col, sizeof(double));
-				mod->mean_array = (double *)calloc(mod->n_item * mod->n_col, sizeof(double));
-				mod->min_array = (double *)calloc(mod->n_item * mod->n_col, sizeof(double));
-			}
-		}
-	}
+    int    i;
+    struct module *mod = NULL;
+
+    for (i = 0; i < statis.total_mod_num; i++) {
+        mod = mods[i];
+        if (!mod->enable) {
+            continue;
+        }
+
+        if (MERGE_ITEM == conf.print_merge) {
+            mod->n_item = 1;
+
+        } else {
+            /* get mod->n_item first, and mod->n_item will be reseted in reading next line */
+            mod->n_item = get_strtok_num(mod->record, ITEM_SPLIT);
+        }
+
+        if (mod->n_item) {
+            mod->pre_array = (U_64 *)calloc(mod->n_item * mod->n_col, sizeof(U_64));
+            mod->cur_array = (U_64 *)calloc(mod->n_item * mod->n_col, sizeof(U_64));
+            mod->st_array = (double *)calloc(mod->n_item * mod->n_col, sizeof(double));
+            if (conf.print_tail) {
+                mod->max_array = (double *)calloc(mod->n_item * mod->n_col, sizeof(double));
+                mod->mean_array = (double *)calloc(mod->n_item * mod->n_col, sizeof(double));
+                mod->min_array = (double *)calloc(mod->n_item * mod->n_col, sizeof(double));
+            }
+        }
+    }
 }
 
 
-/* 
+/*
  * 1. realloc store array when mod->n_item is modify
  */
-void realloc_module_array(struct module *mod, int n_n_item)
+void
+realloc_module_array(struct module *mod, int n_n_item)
 {
-	if (n_n_item > mod->n_item) {
-		if (mod->pre_array) {
-			mod->pre_array = (U_64 *)realloc(mod->pre_array, n_n_item * mod->n_col * sizeof(U_64));
-			mod->cur_array = (U_64 *)realloc(mod->cur_array, n_n_item * mod->n_col * sizeof(U_64));
-			mod->st_array = (double *)realloc(mod->st_array, n_n_item * mod->n_col * sizeof(double));
-			if (conf.print_tail) {
-				mod->max_array = (double *)realloc(mod->max_array, n_n_item * mod->n_col *sizeof(double));
-				mod->mean_array =(double *)realloc(mod->mean_array,n_n_item * mod->n_col *sizeof(double));
-				mod->min_array = (double *)realloc(mod->min_array, n_n_item * mod->n_col *sizeof(double));
-			}
-		} else {
-			mod->pre_array = (U_64 *)calloc(n_n_item * mod->n_col, sizeof(U_64));
-			mod->cur_array = (U_64 *)calloc(n_n_item * mod->n_col, sizeof(U_64));
-			mod->st_array = (double *)calloc(n_n_item * mod->n_col, sizeof(double));
-			if (conf.print_tail) {
-				mod->max_array = (double *)calloc(n_n_item * mod->n_col, sizeof(double));
-				mod->mean_array =(double *)calloc(n_n_item * mod->n_col, sizeof(double));
-				mod->min_array = (double *)calloc(n_n_item * mod->n_col, sizeof(double));
-			}
-		}
-	}
+    if (n_n_item > mod->n_item) {
+        if (mod->pre_array) {
+            mod->pre_array = (U_64 *)realloc(mod->pre_array, n_n_item * mod->n_col * sizeof(U_64));
+            mod->cur_array = (U_64 *)realloc(mod->cur_array, n_n_item * mod->n_col * sizeof(U_64));
+            mod->st_array = (double *)realloc(mod->st_array, n_n_item * mod->n_col * sizeof(double));
+            if (conf.print_tail) {
+                mod->max_array = (double *)realloc(mod->max_array, n_n_item * mod->n_col *sizeof(double));
+                mod->mean_array =(double *)realloc(mod->mean_array, n_n_item * mod->n_col *sizeof(double));
+                mod->min_array = (double *)realloc(mod->min_array, n_n_item * mod->n_col *sizeof(double));
+            }
+
+        } else {
+            mod->pre_array = (U_64 *)calloc(n_n_item * mod->n_col, sizeof(U_64));
+            mod->cur_array = (U_64 *)calloc(n_n_item * mod->n_col, sizeof(U_64));
+            mod->st_array = (double *)calloc(n_n_item * mod->n_col, sizeof(double));
+            if (conf.print_tail) {
+                mod->max_array = (double *)calloc(n_n_item * mod->n_col, sizeof(double));
+                mod->mean_array =(double *)calloc(n_n_item * mod->n_col, sizeof(double));
+                mod->min_array = (double *)calloc(n_n_item * mod->n_col, sizeof(double));
+            }
+        }
+    }
 }
 
 /*
  * set st result in st_array
  */
-void set_st_record(struct module *mod)
+void
+set_st_record(struct module *mod)
 {
-	int i, j, k = 0;	
-	struct mod_info *info = mod->info;
-
-	mod->st_flag = 1;
-
-	for (i = 0; i < mod->n_item; i++) {
-		/* custom statis compute */
-		if (mod->set_st_record) {
-			mod->set_st_record(mod, &mod->st_array[i * mod->n_col], 
-					&mod->pre_array[i * mod->n_col],
-					&mod->cur_array[i * mod->n_col],
-					conf.print_interval);
-		}
-
-		for (j=0; j < mod->n_col; j++) {
-			if (!mod->set_st_record) {
-				switch (info[j].stats_opt) {
-					case STATS_SUB:
-						if (mod->cur_array[k] < mod->pre_array[k]) {
-							mod->pre_array[k] = mod->cur_array[k];
-							mod->st_flag = 0;
-						}
-						else
-							mod->st_array[k] = mod->cur_array[k] - mod->pre_array[k];
-						break;
-					case STATS_SUB_INTER:
-						if (mod->cur_array[k] < mod->pre_array[k]) {
-							mod->pre_array[k] = mod->cur_array[k];
-							mod->st_flag = 0;
-						}
-						else
-							mod->st_array[k] = (mod->cur_array[k] -mod->pre_array[k])/conf.print_interval;
-						break;
-					default:
-						mod->st_array[k] = mod->cur_array[k];	
-				}
-				mod->st_array[k] *= 1.0;
-			}
-
-			if (conf.print_tail) {
-				if (0 == mod->n_record) {
-					mod->max_array[k] = mod->mean_array[k] = mod->min_array[k] = mod->st_array[k]*1.0;
-				} else {
-					if (mod->st_array[k] - mod->max_array[k] > 0.1)
-						mod->max_array[k] = mod->st_array[k];
-					if (mod->min_array[k] - mod->st_array[k] > 0.1 && mod->st_array[k] >= 0)
-						mod->min_array[k] = mod->st_array[k];
-					if(mod->st_array[k] >= 0)
-						mod->mean_array[k] = ((mod->n_record-1) *mod->mean_array[k] + mod->st_array[k])/mod->n_record;
-				}
-			}
-			k++;
-		}
-	}
-
-	mod->n_record++;
+    int    i, j, k = 0;
+    struct mod_info *info = mod->info;
+
+    mod->st_flag = 1;
+
+    for (i = 0; i < mod->n_item; i++) {
+        /* custom statis compute */
+        if (mod->set_st_record) {
+            mod->set_st_record(mod, &mod->st_array[i * mod->n_col],
+                    &mod->pre_array[i * mod->n_col],
+                    &mod->cur_array[i * mod->n_col],
+                    conf.print_interval);
+        }
+
+        for (j=0; j < mod->n_col; j++) {
+            if (!mod->set_st_record) {
+                switch (info[j].stats_opt) {
+                    case STATS_SUB:
+                        if (mod->cur_array[k] < mod->pre_array[k]) {
+                            mod->pre_array[k] = mod->cur_array[k];
+                            mod->st_flag = 0;
+
+                        } else {
+                            mod->st_array[k] = mod->cur_array[k] - mod->pre_array[k];
+                        }
+                        break;
+                    case STATS_SUB_INTER:
+                        if (mod->cur_array[k] < mod->pre_array[k]) {
+                            mod->pre_array[k] = mod->cur_array[k];
+                            mod->st_flag = 0;
+
+                        } else {
+                            mod->st_array[k] = (mod->cur_array[k] -mod->pre_array[k]) / conf.print_interval;
+                        }
+                        break;
+                    default:
+                        mod->st_array[k] = mod->cur_array[k];
+                }
+                mod->st_array[k] *= 1.0;
+            }
+
+            if (conf.print_tail) {
+                if (0 == mod->n_record) {
+                    mod->max_array[k] = mod->mean_array[k] = mod->min_array[k] = mod->st_array[k] * 1.0;
+
+                } else {
+                    if (mod->st_array[k] - mod->max_array[k] > 0.1) {
+                        mod->max_array[k] = mod->st_array[k];
+                    }
+                    if (mod->min_array[k] - mod->st_array[k] > 0.1 && mod->st_array[k] >= 0) {
+                        mod->min_array[k] = mod->st_array[k];
+                    }
+                    if (mod->st_array[k] >= 0) {
+                        mod->mean_array[k] = ((mod->n_record - 1) *mod->mean_array[k] + mod->st_array[k]) / mod->n_record;
+                    }
+                }
+            }
+            k++;
+        }
+    }
+
+    mod->n_record++;
 }
 
 
 /*
- * if diable = 1, then will disable module when record is null 
+ * if diable = 1, then will disable module when record is null
  */
-void collect_record()
+void
+collect_record()
 {
-	struct module *mod = NULL;
-	int  i;
-
-	for (i = 0; i < statis.total_mod_num; i++) {
-		mod = &mods[i];
-		if (!mod->enable)
-			continue;
-
-		memset(mod->record, 0, sizeof(mod->record));
-		if (mod->data_collect)
-			mod->data_collect(mod,mod->parameter);
-	}
+    int    i;
+    struct module *mod = NULL;
+
+    for (i = 0; i < statis.total_mod_num; i++) {
+        mod = mods[i];
+        if (!mod->enable) {
+            continue;
+        }
+
+        memset(mod->record, 0, sizeof(mod->record));
+        if (mod->data_collect) {
+            mod->data_collect(mod, mod->parameter);
+        }
+    }
 }
 
 
 /*
- * computer mod->st_array and swap cur_info to pre_info
+ * compute mod->st_array and swap cur_info to pre_info
  * return:  1 -> ok
- *	    0 -> some mod->n_item have modify will reprint header
+ *      0 -> some mod->n_item have modify will reprint header
  */
-int collect_record_stat()
+int
+collect_record_stat()
 {
-	struct module *mod = NULL;
-	U_64 *tmp, array[MAX_COL_NUM] = {0};
-	int  i, n_item, ret, no_p_hdr = 1;
-
-	for (i = 0; i < statis.total_mod_num; i++) {
-		mod = &mods[i];
-		if (!mod->enable)				
-			continue;
-
-		memset(array, 0, sizeof(array));
-		mod->st_flag = 0;
-		ret = 0;
-
-		if ((n_item = get_strtok_num(mod->record, ITEM_SPLIT))) {
-			/* not merge mode, and last n_item != cur n_item, then reset mod->n_item and set reprint header flag */
-			if (MERGE_ITEM != conf.print_merge && n_item && n_item != mod->n_item) {
-				no_p_hdr = 0;
-				/* reset struct module fields */	
-				realloc_module_array(mod, n_item);
-			}
-
-			mod->n_item = n_item;
-			/* multiply item because of have ITEM_SPLIT */
-			if (strstr(mod->record, ITEM_SPLIT)) {
-				/* merge items */
-				if (MERGE_ITEM == conf.print_merge) {
-					mod->n_item = 1;
-					ret = merge_mult_item_to_array(mod->cur_array, mod);
-				} else {
-					char item[LEN_128] = {0};
-					int num = 0;
-					int pos = 0;
-
-					while (strtok_next_item(item, mod->record, &pos)) {
-						if (!(ret=convert_record_to_array(&mod->cur_array[num * mod->n_col],mod->n_col,item)))
-							break;
-						memset(item, 0, sizeof(item));
-						num++;
-					}
-				}
-			} else { /* one item */
-				ret = convert_record_to_array(mod->cur_array, mod->n_col, mod->record);
-			}
-
-			/* get st record */
-			if (no_p_hdr && mod->pre_flag && ret) {
-				set_st_record(mod);
-			}
-
-			if (!ret)
-				mod->pre_flag = 0;
-			else
-				mod->pre_flag = 1;
-		} else
-			mod->pre_flag = 0;
-		//printf("%s %s\n",mod->cur_array,mod->pre_array);
-		/* swap cur_array to pre_array */
-		tmp = mod->pre_array;
-		mod->pre_array = mod->cur_array;
-		mod->cur_array = tmp;
-	}
-
-	return no_p_hdr;
+    int    i, n_item, ret, no_p_hdr = 1;
+    U_64  *tmp, array[MAX_COL_NUM] = {0};
+    struct module *mod = NULL;
+
+    for (i = 0; i < statis.total_mod_num; i++) {
+        mod = mods[i];
+        if (!mod->enable) {
+            continue;
+        }
+
+        memset(array, 0, sizeof(array));
+        mod->st_flag = 0;
+        ret = 0;
+
+        if ((n_item = get_strtok_num(mod->record, ITEM_SPLIT))) {
+            /* not merge mode, and last n_item != cur n_item, then reset mod->n_item and set reprint header flag */
+            if (MERGE_ITEM != conf.print_merge && n_item && n_item != mod->n_item) {
+                no_p_hdr = 0;
+                /* reset struct module fields */
+                realloc_module_array(mod, n_item);
+            }
+
+            mod->n_item = n_item;
+            /* multiple item because of having ITEM_SPLIT */
+            if (strpbrk(mod->record, ITEM_SPLIT)) {
+                /* merge items */
+                if (MERGE_ITEM == conf.print_merge) {
+                    mod->n_item = 1;
+                    ret = merge_mult_item_to_array(mod->cur_array, mod);
+
+                } else {
+                    char *item;
+                    int num = 0;
+                    int pos = 0;
+
+                    while ((item = strtok_next_item(mod->record, &pos)) != NULL) {
+                        if ((ret=convert_record_to_array(&mod->cur_array[num * mod->n_col], mod->n_col, item)) <= 0) {
+                            break;
+                        }
+                        num++;
+                    }
+                }
+
+            } else { /* one item */
+                ret = convert_record_to_array(mod->cur_array, mod->n_col, mod->record);
+            }
+
+            /* get st record */
+            if (no_p_hdr && mod->pre_flag && ret) {
+                set_st_record(mod);
+            }
+
+            if (!ret) {
+                mod->pre_flag = 0;
+
+            } else {
+                mod->pre_flag = 1;
+            }
+
+        } else {
+            mod->pre_flag = 0;
+        }
+        /* swap cur_array to pre_array */
+        tmp = mod->pre_array;
+        mod->pre_array = mod->cur_array;
+        mod->cur_array = tmp;
+    }
+
+    return no_p_hdr;
 }
 
 
 /*
  * free module info
  */
-void free_modules()
+void
+free_modules()
 {
-	int	i;
-	struct	module *mod;
-
-	for (i = 0; i < statis.total_mod_num; i++) {
-		mod = &mods[i];
-		if (mod->lib)
-			dlclose(mod->lib);
-
-		if (mod->cur_array) {
-			free(mod->cur_array);
-			mod->cur_array = NULL;
-			free(mod->pre_array);
-			mod->pre_array = NULL;
-			free(mod->st_array);
-			mod->st_array = NULL;
-		}
-
-		if (mod->max_array) {
-			free(mod->max_array);
-			free(mod->mean_array);
-			free(mod->min_array);
-			mod->max_array = NULL;
-			mod->mean_array = NULL;
-			mod->min_array = NULL;
-		}
-	}
+    int    i;
+    struct module *mod;
+
+    for (i = 0; i < statis.total_mod_num; i++) {
+        mod = mods[i];
+        if (mod->lib) {
+            dlclose(mod->lib);
+        }
+
+        if (mod->cur_array) {
+            free(mod->cur_array);
+            mod->cur_array = NULL;
+            free(mod->pre_array);
+            mod->pre_array = NULL;
+            free(mod->st_array);
+            mod->st_array = NULL;
+        }
+
+        if (mod->max_array) {
+            free(mod->max_array);
+            free(mod->mean_array);
+            free(mod->min_array);
+            mod->max_array = NULL;
+            mod->mean_array = NULL;
+            mod->min_array = NULL;
+        }
+	free(mod);
+    }
 }
 
 
 /*
- * read line from file to mod->record 
+ * read line from file to mod->record and return timestamp
  */
-void read_line_to_module_record(char *line)
+time_t
+read_line_to_module_record(char *line)
 {
-	int	i;
-	struct	module *mod;
-	char	*s_token, *e_token;
-
-	line[strlen(line) - 1] = '\0';
-	for (i = 0; i < statis.total_mod_num; i++) {
-		mod = &mods[i];
-		if (mod->enable) {
-			memset(mod->record, 0, sizeof(mod->record));
-
-			s_token = strstr(line, mod->opt_line);
-			if (!s_token) {
-				continue;
-			}
-
-			s_token += strlen(mod->opt_line) + sizeof(STRING_SPLIT) - 1;
-			e_token = strstr(s_token, SECTION_SPLIT);
-
-			if (e_token)
-				memcpy(mod->record, s_token, e_token - s_token);
-			else
-				memcpy(mod->record, s_token, strlen(line) - (s_token - line));
-		}
-	}
+    int    i;
+    struct module *mod;
+    char  *s_token, *e_token;
+    char   mod_opt[LEN_64];
+
+    line[strlen(line) - 1] = '\0';
+    for (i = 0; i < statis.total_mod_num; i++) {
+        mod = mods[i];
+        if (mod->enable) {
+            sprintf(mod_opt, "%s%s%s", SECTION_SPLIT, mod->opt_line, STRING_SPLIT);
+            memset(mod->record, 0, sizeof(mod->record));
+
+            s_token = strstr(line, mod_opt);
+            if (!s_token) {
+                continue;
+            }
+
+            s_token += strlen(mod->opt_line) + 2;
+            e_token = strpbrk(s_token, SECTION_SPLIT);
+
+            if (e_token) {
+                memcpy(mod->record, s_token, e_token - s_token);
+
+            } else {
+                memcpy(mod->record, s_token, strlen(line) - (s_token - line));
+            }
+        }
+    }
+    return atol(line);
 }
 
 
 /*
  * if col num is zero then disable module
  */
-void disable_col_zero()
+void
+disable_col_zero()
 {
-	struct module *mod = NULL;
-	int  i, j;
-
-	for (i = 0; i < statis.total_mod_num; i++) {
-		mod = &mods[i];
-		if (!mod->enable)	
-			continue;
-
-		if (!mod->n_col)
-			mod->enable = 0;
-		else {
-			struct mod_info *info = mod->info;
-			int p_col = 0;
-
-			for (j = 0; j < mod->n_col; j++) {
-				if (((DATA_SUMMARY == conf.print_mode) && (SUMMARY_BIT == info[j].summary_bit)) 
-						|| ((DATA_DETAIL == conf.print_mode) && (HIDE_BIT != info[j].summary_bit))) {
-					p_col++;
-					break;
-				}
-			}
-
-			if (!p_col)
-				mod->enable = 0;
-		}
-	}
+    int    i, j;
+    struct module *mod = NULL;
+    int    p_col;
+    struct mod_info *info;
+
+    for (i = 0; i < statis.total_mod_num; i++) {
+        mod = mods[i];
+        if (!mod->enable) {
+            continue;
+        }
+
+        if (!mod->n_col) {
+            mod->enable = 0;
+
+        } else {
+            p_col = 0;
+            info = mod->info;
+
+            for (j = 0; j < mod->n_col; j++) {
+                if (((DATA_SUMMARY == conf.print_mode) && (SUMMARY_BIT == info[j].summary_bit))
+                        || ((DATA_DETAIL == conf.print_mode) && (HIDE_BIT != info[j].summary_bit))) {
+                    p_col++;
+                    break;
+                }
+            }
+
+            if (!p_col) {
+                mod->enable = 0;
+            }
+        }
+    }
 }
+
diff --git a/src/output_db.c b/src/output_db.c
index 711f6c3..acdc6f8 100644
--- a/src/output_db.c
+++ b/src/output_db.c
@@ -1,3 +1,4 @@
+
 /*
  * (C) 2010-2011 Alibaba Group Holding Limited
  *
@@ -15,186 +16,201 @@
  *
  */
 
+
 #include <fcntl.h>
 #include "tsar.h"
 
+
 /*
  * send sql to remote db
  */
-void send_sql_txt(int fd, int have_collect)
+void
+send_sql_txt(int fd, int have_collect)
 {
-	struct	module *mod;
-	char	sqls[LEN_10240] = {0};
-	char	s_time[LEN_64] = {0};
-	char	host_name[LEN_64] = {0};
-	int	i = 0, j;
-
-	/* get hostname */
-	if (0 != gethostname(host_name, sizeof(host_name))) {
-		do_debug(LOG_FATAL, "send_sql_txt: gethostname err, errno=%d", errno);
-	}
-	while (host_name[i]) {
-		if (!isprint(host_name[i++])) {
-			host_name[i-1] = '\0';
-			break;
-		}
-	}
-
-	/* get st_array */
-	if (get_st_array_from_file(have_collect))
-		return;
-
-	/* only output from output_db_mod */
-	reload_modules(conf.output_db_mod);
-
-	sprintf(s_time, "%ld", time(NULL));
-
-	/* print summary data */
-	for (i = 0; i < statis.total_mod_num; i++) {
-		mod = &mods[i];
-		if (!mod->enable)
-			continue;
-		else if (!mod->st_flag) {
-			char	sql_hdr[LEN_256] = {0};
-			/* set sql header */
-			memset(sql_hdr, '\0', sizeof(sql_hdr));
-			sprintf(sql_hdr, "insert into `%s` (host_name, time) VALUES ('%s', '%s');",
-					mod->opt_line+2, host_name, s_time);
-			strcat(sqls, sql_hdr);
-		} else {
-			char	str[LEN_32] = {0};
-			char	sql_hdr[LEN_256] = {0};
-			struct  mod_info *info = mod->info;
-
-			/* set sql header */
-			memset(sql_hdr, '\0', sizeof(sql_hdr));
-			sprintf(sql_hdr, "insert into `%s` (host_name, time", mod->opt_line+2);
-
-			/* get value */
-			for (j = 0; j < mod->n_col; j++) {
-				strcat(sql_hdr, ", `");
-				char *p = info[j].hdr;
-				while(*p == ' ')
-					p++;
-				strcat(sql_hdr, p);
-				strcat(sql_hdr, "`");
-			}
-			strcat(sql_hdr, ") VALUES ('");
-			strcat(sql_hdr, host_name);
-			strcat(sql_hdr, "', '");
-			strcat(sql_hdr, s_time);
-			strcat(sql_hdr, "'");
-			strcat(sqls, sql_hdr);
-
-			/* get value */
-			for (j = 0; j < mod->n_col; j++) {
-				memset(str, 0, sizeof(str));
-				sprintf(str, ", '%.1f'", mod->st_array[j]);
-				strcat(sqls, str);
-			}
-			strcat(sqls, ");");
-		}
-	}
-	write(fd, sqls, strlen(sqls));
+    int         i = 0, j, len;
+    char        s_time[LEN_64] = {0};
+    char        host_name[LEN_64] = {0};
+    struct      module *mod;
+    static char sqls[LEN_10M] = {0};
+
+    /* get hostname */
+    if (0 != gethostname(host_name, sizeof(host_name))) {
+        do_debug(LOG_FATAL, "send_sql_txt: gethostname err, errno=%d", errno);
+    }
+    while (host_name[i]) {
+        if (!isprint(host_name[i++])) {
+            host_name[i-1] = '\0';
+            break;
+        }
+    }
+
+    /* get st_array */
+    if (get_st_array_from_file(have_collect)) {
+        return;
+    }
+
+    /* only output from output_db_mod */
+    reload_modules(conf.output_db_mod);
+
+    sprintf(s_time, "%ld", time(NULL));
+
+    /* print summary data */
+    for (i = 0; i < statis.total_mod_num; i++) {
+        mod = mods[i];
+        if (!mod->enable) {
+            continue;
+
+        } else {
+            if (!mod->st_flag) {
+                char    sql_hdr[LEN_256] = {0};
+                /* set sql header */
+                memset(sql_hdr, '\0', sizeof(sql_hdr));
+                sprintf(sql_hdr, "insert into `%s` (host_name, time) VALUES ('%s', '%s');",
+                        mod->opt_line + 2, host_name, s_time);
+                strcat(sqls, sql_hdr);
+
+            } else {
+                char    str[LEN_32] = {0};
+                char    sql_hdr[LEN_256] = {0};
+                struct  mod_info *info = mod->info;
+
+                /* set sql header */
+                memset(sql_hdr, '\0', sizeof(sql_hdr));
+                sprintf(sql_hdr, "insert into `%s` (host_name, time", mod->opt_line + 2);
+
+                /* get value */
+                for (j = 0; j < mod->n_col; j++) {
+                    strcat(sql_hdr, ", `");
+                    char *p = info[j].hdr;
+                    while (*p == ' ') {
+                        p++;
+                    }
+                    strncat(sql_hdr, p, LEN_128);
+                    strcat(sql_hdr, "`");
+                }
+                strcat(sql_hdr, ") VALUES ('");
+                strcat(sql_hdr, host_name);
+                strcat(sql_hdr, "', '");
+                strcat(sql_hdr, s_time);
+                strcat(sql_hdr, "'");
+                strcat(sqls, sql_hdr);
+
+                /* get value */
+                for (j = 0; j < mod->n_col; j++) {
+                    memset(str, 0, sizeof(str));
+                    sprintf(str, ", '%.1f'", mod->st_array[j]);
+                    strcat(sqls, str);
+                }
+                strcat(sqls, ");");
+            }
+        }
+    }
+    len = strlen(sqls);
+    if (write(fd, sqls, len) != len) {
+        do_debug(LOG_ERR, "output_db write error:%s", strerror(errno));
+    }
 }
 
-
-struct sockaddr_in *str2sa(char *str)
+struct sockaddr_in *
+str2sa(char *str)
 {
-	static	struct sockaddr_in sa;
-	char	*c;
-	int	port;
-
-	memset(&sa, 0, sizeof(sa));
-	str = strdup(str);
-	if (str == NULL)
-		goto out_nofree;
-
-	if ((c = strrchr(str,':')) != NULL) {
-		*c++ = '\0';
-		port = atol(c);
-	}
-	else
-		port = 0;
-
-	if (*str == '*' || *str == '\0') { /* INADDR_ANY */
-		sa.sin_addr.s_addr = INADDR_ANY;
-	}
-	else if (!inet_pton(AF_INET, str, &sa.sin_addr)) {
-		struct hostent *he;
-
-		if ((he = gethostbyname(str)) == NULL) {
-			do_debug(LOG_FATAL, "str2sa: Invalid server name, '%s'", str);
-		}
-		else
-			sa.sin_addr = *(struct in_addr *) *(he->h_addr_list);
-	}
-	sa.sin_port   = htons(port);
-	sa.sin_family = AF_INET;
-
-	free(str);
+    int                       port;
+    char                     *c;
+    static struct sockaddr_in sa;
+
+    memset(&sa, 0, sizeof(sa));
+    str = strdup(str);
+    if (str == NULL) {
+        goto out_nofree;
+    }
+
+    if ((c = strrchr(str, ':')) != NULL) {
+        *c++ = '\0';
+        port = atol(c);
+
+    } else {
+        port = 0;
+    }
+
+    if (*str == '*' || *str == '\0') { /* INADDR_ANY */
+        sa.sin_addr.s_addr = INADDR_ANY;
+
+    } else {
+        if (!inet_pton(AF_INET, str, &sa.sin_addr)) {
+            struct hostent *he;
+
+            if ((he = gethostbyname(str)) == NULL) {
+                do_debug(LOG_FATAL, "str2sa: Invalid server name, '%s'", str);
+
+            } else {
+                sa.sin_addr = *(struct in_addr *) *(he->h_addr_list);
+            }
+        }
+    }
+    sa.sin_port   = htons(port);
+    sa.sin_family = AF_INET;
+
+    free(str);
 out_nofree:
-	return &sa;
+    return &sa;
 }
 
-
-void output_db(int have_collect)
+void
+output_db(int have_collect)
 {
-	struct	sockaddr_in db_addr;
-	int	fd, flags, res;
-	fd_set	fdr, fdw;
-	struct	timeval timeout;
-
-	fd = socket(AF_INET, SOCK_STREAM, 0);
-	if (fd < 0) {
-		do_debug(LOG_FATAL, "can't get socket");
-	}
-
-	/* set socket fd noblock */
-	if((flags = fcntl(fd, F_GETFL, 0)) < 0) {
-		close(fd);
-		return;
-	}
-
-	if(fcntl(fd, F_SETFL, flags | O_NONBLOCK) < 0) {
-		close(fd);
-		return;
-	}
-
-	/* get db server address */
-	db_addr = *str2sa(conf.output_db_addr);
-
-	if (connect(fd, (struct sockaddr*)&db_addr, sizeof(db_addr)) != 0) {
-		if (errno != EINPROGRESS) { // EINPROGRESS
-			close(fd);
-			return;
-		}
-		else
-			goto select;
-	}
-	else
-		goto send;
+    int        fd, flags, res;
+    fd_set     fdr, fdw;
+    struct     timeval timeout;
+    struct     sockaddr_in db_addr;
+
+    fd = socket(AF_INET, SOCK_STREAM, 0);
+    if (fd < 0) {
+        do_debug(LOG_FATAL, "can't get socket");
+    }
+
+    /* set socket fd noblock */
+    if ((flags = fcntl(fd, F_GETFL, 0)) < 0) {
+        close(fd);
+        return;
+    }
+
+    if (fcntl(fd, F_SETFL, flags | O_NONBLOCK) < 0) {
+        close(fd);
+        return;
+    }
+
+    /* get db server address */
+    db_addr = *str2sa(conf.output_db_addr);
+
+    if (connect(fd, (struct sockaddr*)&db_addr, sizeof(db_addr)) != 0) {
+        if (errno != EINPROGRESS) { // EINPROGRESS
+            close(fd);
+            return;
+
+        } else {
+            goto select;
+        }
+
+    } else {
+        goto send;
+    }
 
 select:
-	FD_ZERO(&fdr);
-	FD_ZERO(&fdw);
-	FD_SET(fd, &fdr);
-	FD_SET(fd, &fdw);
-
-	timeout.tv_sec = 2;
-	timeout.tv_usec = 0;
-
-	res = select(fd + 1, &fdr, &fdw, NULL, &timeout);
-	if(res < 0) {
-		close(fd);
-		return;
-	}
-	if(res == 0) {
-		close(fd);
-		return;
-	}
+    FD_ZERO(&fdr);
+    FD_ZERO(&fdw);
+    FD_SET(fd, &fdr);
+    FD_SET(fd, &fdw);
+
+    timeout.tv_sec = 2;
+    timeout.tv_usec = 0;
+
+    res = select(fd + 1, &fdr, &fdw, NULL, &timeout);
+    if (res <= 0) {
+        close(fd);
+        return;
+    }
 
 send:
-	send_sql_txt(fd, have_collect);
-	close(fd);
+    send_sql_txt(fd, have_collect);
+    close(fd);
 }
diff --git a/src/output_file.c b/src/output_file.c
index 4bc260c..0e79df0 100644
--- a/src/output_file.c
+++ b/src/output_file.c
@@ -1,3 +1,4 @@
+
 /*
  * (C) 2010-2011 Alibaba Group Holding Limited
  *
@@ -15,42 +16,52 @@
  *
  */
 
+
 #include "tsar.h"
 
-void output_file()
+
+void
+output_file()
 {
-	struct	module *mod;
-	FILE	*fp = NULL;
-	int	i, ret = 0;
-	char	line[LEN_10240] = {0};
-	char	detail[LEN_4096] = {0};
-	char	s_time[LEN_256] = {0};
-
-	if (!(fp = fopen(conf.output_file_path, "a+"))) {
-		if (!(fp = fopen(conf.output_file_path, "w")))
-			do_debug(LOG_FATAL, "output_file: can't create data file = %s  err=%d\n", conf.output_file_path, errno);
-	}
-
-	sprintf(s_time, "%ld", statis.cur_time);
-	strcat(line, s_time);
-
-	for (i = 0; i < statis.total_mod_num; i++) {
-		mod = &mods[i];
-		if (mod->enable && strlen(mod->record)) {
-			/* save collect data to output_file */
-			sprintf(detail, "%s%s%s%s", SECTION_SPLIT, mod->opt_line, STRING_SPLIT, mod->record);
-			strcat(line, detail);
-			ret = 1;
-		}
-	}
-	strcat(line, "\n");
-
-	if (ret) {
-		if(fputs(line, fp) < 0)
-			do_debug(LOG_WARN, "write line error\n");
-	}
-	fclose(fp);
-	if(chmod(conf.output_file_path, 0666) < 0 )
-		do_debug(LOG_WARN, "chmod file %s error\n",conf.output_file_path);
-}
+    int         i, ret = 0, n = 0;
+    FILE       *fp = NULL;
+    char        detail[LEN_1M] = {0};
+    char        s_time[LEN_256] = {0};
+    struct      module *mod;
+    static char line[LEN_10M] = {0};
 
+    if (!(fp = fopen(conf.output_file_path, "a"))) {
+        do_debug(LOG_FATAL, "output_file: can't open or create data file = %s  err=%d\n", conf.output_file_path, errno);
+    }
+    setbuf(fp, NULL);
+
+    sprintf(s_time, "%ld", statis.cur_time);
+    strcat(line, s_time);
+
+    for (i = 0; i < statis.total_mod_num; i++) {
+        mod = mods[i];
+        if (mod->enable && strlen(mod->record)) {
+            /* save collect data to output_file */
+            n = snprintf(detail, LEN_1M, "%s%s%s%s", SECTION_SPLIT, mod->opt_line, STRING_SPLIT, mod->record);
+            if (n >= LEN_1M - 1) {
+                do_debug(LOG_FATAL, "mod %s lenth is overflow %d\n", mod->name, n);
+            }
+	    /* one for \n one for \0 */
+            if (strlen(line) + strlen(detail) >= LEN_10M - 2) {
+                do_debug(LOG_FATAL, "tsar.data line lenth is overflow line %d detail %d\n", strlen(line), strlen(detail));
+            }
+            strcat(line, detail);
+            ret = 1;
+        }
+    }
+    strcat(line, "\n");
+
+    if (ret) {
+        if (fputs(line, fp) < 0) {
+            do_debug(LOG_ERR, "write line error\n");
+        }
+    }
+    if (fclose(fp) < 0) {
+        do_debug(LOG_FATAL, "fclose error:%s", strerror(errno));
+    }
+}
diff --git a/src/output_nagios.c b/src/output_nagios.c
index 1a6f10d..49eaf60 100644
--- a/src/output_nagios.c
+++ b/src/output_nagios.c
@@ -1,3 +1,4 @@
+
 /*
  * (C) 2010-2011 Alibaba Group Holding Limited
  *
@@ -15,135 +16,151 @@
  *
  */
 
+
 #include <fcntl.h>
 #include "tsar.h"
 
-#define PRE_RECORD_FILE		"/tmp/.tsar.tmp"
-
-void output_nagios(){
-	struct	module *mod;
-	int	result = 0;
-	char	output[LEN_4096] = {0};
-	char	output_err[LEN_4096] = {0};
-	char	s_time[LEN_64] = {0};
-	char	host_name[LEN_64] = {0};
-	int	i = 0, j = 0, k = 0, l = 0;
-	/* if cycle time ok*/
-	int	now_time;
-	now_time = statis.cur_time - statis.cur_time%60;
-	if ((*conf.cycle_time) == 0 || now_time%*(conf.cycle_time) != 0)
-		return;
-
-	/* get hostname */
-	if (0 != gethostname(host_name, sizeof(host_name))) {
-		do_debug(LOG_FATAL, "send to nagios: gethostname err, errno=%d \n", errno);
-	}
-	while (host_name[i]) {
-		if (!isprint(host_name[i++])) {
-			host_name[i-1] = '\0';
-			break;
-		}
-	}
-
-	/* update module parameter */
-	conf.print_merge = MERGE_NOT;
-
-	/* get st_array */
-	if (get_st_array_from_file(0))
-		return;
-
-	/* only output from output_nagios_mod */
-	reload_modules(conf.output_nagios_mod);
-
-	sprintf(s_time, "%ld", time(NULL));
-
-	/* print summary data */
-	for (i = 0; i < statis.total_mod_num; i++) {
-		mod = &mods[i];
-		if (!mod->enable)
-			continue;
-		else if (!mod->st_flag) {
-			printf("name %s\n",mod->name);
-			printf("do nothing\n");
-		}else {
-			char opt[LEN_32];
-			char check[LEN_64];
-			char *n_record = strdup(mod->record);
-			char *token = strtok(n_record, ITEM_SPLIT);
-			char *s_token;
-			double  *st_array;
-			struct mod_info *info = mod->info;
-			j = 0;
-			//get mod_name.(item_name).col_name value
-			while (token) {
-				memset(check, 0, sizeof(check));
-				strcat(check,mod->name+4);
-				strcat(check,".");
-				s_token = strstr(token, ITEM_SPSTART);
-				//multi item
-				if(s_token){
-					memset(opt, 0, sizeof(opt));
-					strncat(opt, token, s_token - token);
-					strcat(check,opt);
-					strcat(check,".");
-				}
-				//get value
-				st_array = &mod->st_array[j * mod->n_col];
-				token = strtok(NULL, ITEM_SPLIT);
-				j++;
-				for (k = 0; k < mod->n_col; k++) {
-					char check_item[LEN_64];
-					char *p;
-					memset(check_item,0,LEN_64);
-					memcpy(check_item,check,LEN_64);
-					p = info[k].hdr;
-					while(*p == ' ')
-						p++;
-					strcat(check_item,p);
-					for(l = 0; l < conf.mod_num; l++){
-						/* cmp tsar item with naigos item*/
-						if(!strcmp(conf.check_name[l],check_item))
-						{
-							char value[LEN_32];
-							memset(value,0,sizeof(value));
-							sprintf(value,"%0.2f",st_array[k]);
-							strcat(output,check_item);
-							strcat(output,"=");
-							strcat(output,value);
-							strcat(output," ");
-							if( conf.cmin[l] != 0 && st_array[k] >= conf.cmin[l] ){
-								if( conf.cmax[l] == 0 || (conf.cmax[l] != 0 && st_array[k] <= conf.cmax[l]) ){
-									result = 2;
-									strcat(output_err,check_item);
-									strcat(output_err,"=");
-									strcat(output_err,value);
-									strcat(output_err," ");
-									continue;
-								}
-							}
-							if( conf.wmin[l] != 0 && st_array[k] >= conf.wmin[l] ){
-								if( conf.wmax[l] == 0 || (conf.wmax[l] != 0 && st_array[k] <= conf.wmax[l]) ){
-									if( result != 2)
-										result = 1;
-									strcat(output_err,check_item);
-									strcat(output_err,"=");
-									strcat(output_err,value);
-									strcat(output_err," ");
-								}
-							}
-						}
-					}
-				}
-			}
-		}
-	}
-	if(!strcmp(output_err,""))
-		strcat(output_err,"OK");
-	/* send to nagios server*/
-	char nagios_cmd[LEN_1024];
-	sprintf(nagios_cmd,"echo \"%s;tsar;%d;%s|%s\"|%s -H %s -p %d -to 10 -d \";\" -c %s",host_name,result,output_err,output,conf.send_nsca_cmd,conf.server_addr,*(conf.server_port),conf.send_nsca_conf);
-	do_debug(LOG_DEBUG,"send to naigos:%s\n",nagios_cmd);
-	if(system(nagios_cmd) != 0)
-		do_debug(LOG_WARN,"nsca run error:%s\n",nagios_cmd);;
-	printf("%s\n",nagios_cmd);
+
+#define PRE_RECORD_FILE     "/tmp/.tsar.tmp"
+
+
+void
+output_nagios()
+{
+    int         i = 0, j = 0, k = 0, l = 0, result = 0, now_time;
+    char        s_time[LEN_64] = {0};
+    char        host_name[LEN_64] = {0};
+    struct      module *mod;
+    static char output[LEN_10M] = {0};
+    static char output_err[LEN_10M] = {0};
+
+    /* if cycle time ok*/
+    now_time = statis.cur_time - statis.cur_time%60;
+    if (conf.cycle_time == 0 || now_time%conf.cycle_time != 0) {
+        return;
+    }
+
+    /* get hostname */
+    if (0 != gethostname(host_name, sizeof(host_name))) {
+        do_debug(LOG_FATAL, "send to nagios: gethostname err, errno=%d \n", errno);
+    }
+    while (host_name[i]) {
+        if (!isprint(host_name[i++])) {
+            host_name[i-1] = '\0';
+            break;
+        }
+    }
+
+    /* update module parameter */
+    conf.print_merge = MERGE_NOT;
+
+    /* get st_array */
+    if (get_st_array_from_file(0)) {
+        return;
+    }
+
+    /* only output from output_nagios_mod */
+    reload_modules(conf.output_nagios_mod);
+
+    sprintf(s_time, "%ld", time(NULL));
+
+    /* print summary data */
+    for (i = 0; i < statis.total_mod_num; i++) {
+        mod = mods[i];
+        if (!mod->enable) {
+            continue;
+
+        } else {
+            if (!mod->st_flag) {
+                printf("name %s\n", mod->name);
+                printf("do nothing\n");
+
+            } else {
+                char                opt[LEN_32];
+                char                check[LEN_64];
+                char               *n_record = strdup(mod->record);
+                char               *token = strtok(n_record, ITEM_SPLIT);
+                char               *s_token;
+                double             *st_array;
+                struct mod_info    *info = mod->info;
+
+                j = 0;
+                /* get mod_name.(item_name).col_name value */
+                while (token) {
+                    memset(check, 0, sizeof(check));
+                    strncat(check, mod->name + 4, LEN_32);
+                    strcat(check, ".");
+                    s_token = strpbrk(token, ITEM_SPSTART);
+                    /* multi item */
+                    if (s_token){
+                        memset(opt, 0, sizeof(opt));
+                        strncat(opt, token, s_token - token);
+                        strcat(check, opt);
+                        strcat(check, ".");
+                    }
+                    /* get value */
+                    st_array = &mod->st_array[j * mod->n_col];
+                    token = strtok(NULL, ITEM_SPLIT);
+                    j++;
+                    for (k = 0; k < mod->n_col; k++) {
+                        char    *p;
+                        char    check_item[LEN_64];
+
+                        memset(check_item, 0, LEN_64);
+                        memcpy(check_item, check, LEN_64);
+                        p = info[k].hdr;
+                        while (*p == ' ') {
+                            p++;
+                        }
+                        strncat(check_item, p, LEN_64);
+                        for (l = 0; l < conf.mod_num; l++){
+                            /* cmp tsar item with naigos item*/
+                            if (!strcmp(conf.check_name[l], check_item)) {
+                                char    value[LEN_32];
+                                memset(value, 0, sizeof(value));
+                                sprintf(value, "%0.2f", st_array[k]);
+                                strncat(output, check_item, LEN_64);
+                                strcat(output, "=");
+                                strncat(output, value, LEN_32);
+                                strcat(output, " ");
+                                if (conf.cmin[l] != 0 && st_array[k] >= conf.cmin[l]) {
+                                    if (conf.cmax[l] == 0 || (conf.cmax[l] != 0 && st_array[k] <= conf.cmax[l])) {
+                                        result = 2;
+                                        strncat(output_err, check_item, LEN_64);
+                                        strcat(output_err, "=");
+                                        strncat(output_err, value, LEN_32);
+                                        strcat(output_err, " ");
+                                        continue;
+                                    }
+                                }
+                                if (conf.wmin[l] != 0 && st_array[k] >= conf.wmin[l]) {
+                                    if (conf.wmax[l] == 0 || (conf.wmax[l] != 0 && st_array[k] <= conf.wmax[l]) ) {
+                                        if (result != 2) {
+                                            result = 1;
+                                        }
+                                        strncat(output_err, check_item, LEN_64);
+                                        strcat(output_err, "=");
+                                        strncat(output_err, value, LEN_32);
+                                        strcat(output_err, " ");
+                                    }
+                                }
+                            }
+                        }
+                    }
+                }
+                free(n_record);
+            }
+        }
+    }
+    if (!strcmp(output_err, "")) {
+        strcat(output_err, "OK");
+    }
+    /* send to nagios server*/
+    char    nagios_cmd[LEN_1024];
+    sprintf(nagios_cmd, "echo \"%s;tsar;%d;%s|%s\"|%s -H %s -p %d -to 10 -d \";\" -c %s", host_name, result, output_err, output, conf.send_nsca_cmd, conf.server_addr, conf.server_port, conf.send_nsca_conf);
+    do_debug(LOG_DEBUG, "send to naigos:%s\n", nagios_cmd);
+    if (system(nagios_cmd) != 0) {
+        do_debug(LOG_WARN, "nsca run error:%s\n", nagios_cmd);
+    }
+    printf("%s\n", nagios_cmd);
 }
diff --git a/src/output_print.c b/src/output_print.c
index 2dd910d..44a2804 100644
--- a/src/output_print.c
+++ b/src/output_print.c
@@ -1,3 +1,4 @@
+
 /*
  * (C) 2010-2011 Alibaba Group Holding Limited
  *
@@ -15,1017 +16,1211 @@
  *
  */
 
+
 #include "tsar.h"
+#include <fnmatch.h>
+
 
 /*
  * adjust print opt line
  */
-void adjust_print_opt_line(char *n_opt_line, char *opt_line, int hdr_len)
+void
+adjust_print_opt_line(char *n_opt_line, const char *opt_line, int hdr_len)
 {
-	char pad[LEN_128] = {0};
-	int  pad_len;
-
-	if (hdr_len > strlen(opt_line)) {
-		pad_len = (hdr_len - strlen(opt_line))/2;
-
-		memset(pad, '-', pad_len);
-		strcat(n_opt_line, pad);
-		strcat(n_opt_line, opt_line);
-		memset(&pad, '-', hdr_len - pad_len - strlen(opt_line));
-		strcat(n_opt_line, pad);
-	} else
-		strncat(n_opt_line, opt_line, hdr_len);
+    int    pad_len;
+    char   pad[LEN_128] = {0};
+
+    if (hdr_len > strlen(opt_line)) {
+        pad_len = (hdr_len - strlen(opt_line)) / 2;
+
+        memset(pad, '-', pad_len);
+        strcat(n_opt_line, pad);
+        strcat(n_opt_line, opt_line);
+        memset(pad, '-', hdr_len - pad_len - strlen(opt_line));
+        strcat(n_opt_line, pad);
+
+    } else {
+        strncat(n_opt_line, opt_line, hdr_len);
+    }
 }
 
 
 /*
  * print header and update mod->n_item
  */
-void print_header()
+void
+print_header()
 {
-	struct module *mod = NULL;
-	char header[LEN_10240] = {0};
-	char opt_line[LEN_10240] = {0};
-	char hdr_line[LEN_10240] = {0};
-	char opt[LEN_128] = {0};
-	char n_opt[LEN_256] = {0};
-	char mod_hdr[LEN_256] = {0};
-	char *token, *s_token, *n_record;
-	int i;
-
-	if(conf.running_mode == RUN_PRINT_LIVE){
-		sprintf(opt_line, "Time             %s", PRINT_SEC_SPLIT);
-		sprintf(hdr_line, "Time             %s", PRINT_SEC_SPLIT);
-	}else{
-		sprintf(opt_line, "Time          %s", PRINT_SEC_SPLIT);
-		sprintf(hdr_line, "Time          %s", PRINT_SEC_SPLIT);
-	}
-
-	for (i = 0; i < statis.total_mod_num; i++) {
-		mod = &mods[i];
-		if (!mod->enable)
-			continue;
-
-		memset(n_opt, 0, sizeof(n_opt));
-		memset(mod_hdr, 0, sizeof(mod_hdr));
-		get_mod_hdr(mod_hdr, mod);
-
-		if (strstr(mod->record, ITEM_SPLIT) && MERGE_NOT == conf.print_merge) {
-			n_record = strdup(mod->record);
-			/* set print opt line */
-			token = strtok(n_record, ITEM_SPLIT);
-			while (token) {
-				s_token = strstr(token, ITEM_SPSTART);
-				if (s_token) {
-					memset(opt, 0, sizeof(opt));
-					memset(n_opt, 0, sizeof(n_opt));
-					strncat(opt, token, s_token - token);
-					adjust_print_opt_line(n_opt, opt, strlen(mod_hdr));
-					strcat(opt_line, n_opt);
-					strcat(opt_line, PRINT_SEC_SPLIT);
-					strcat(hdr_line, mod_hdr);
-					strcat(hdr_line, PRINT_SEC_SPLIT);
-				}
-				token = strtok(NULL, ITEM_SPLIT);
-			}
-
-			free(n_record);
-			n_record = NULL;
-		} else {
-			memset(opt, 0, sizeof(opt));
-			/* set print opt line */
-
-			adjust_print_opt_line(opt, mod->opt_line, strlen(mod_hdr));
-
-			/* set print hdr line */
-			strcat(hdr_line, mod_hdr);
-			strcat(opt_line, opt);
-		}
-
-		strcat(hdr_line, PRINT_SEC_SPLIT);
-		strcat(opt_line, PRINT_SEC_SPLIT);
-	}
-
-	sprintf(header, "%s\n%s\n", opt_line, hdr_line);
-	printf("%s", header);
+    int    i;
+    char   header[LEN_1M] = {0};
+    char   opt_line[LEN_1M] = {0};
+    char   hdr_line[LEN_1M] = {0};
+    char   opt[LEN_256] = {0};
+    char   n_opt[LEN_256] = {0};
+    char   mod_hdr[LEN_256] = {0};
+    char  *token, *s_token, *n_record;
+    struct module *mod = NULL;
+
+    if (conf.running_mode == RUN_PRINT_LIVE) {
+        sprintf(opt_line, "Time             %s", PRINT_SEC_SPLIT);
+        sprintf(hdr_line, "Time             %s", PRINT_SEC_SPLIT);
+
+    } else {
+        sprintf(opt_line, "Time          %s", PRINT_SEC_SPLIT);
+        sprintf(hdr_line, "Time          %s", PRINT_SEC_SPLIT);
+    }
+
+    for (i = 0; i < statis.total_mod_num; i++) {
+        mod = mods[i];
+        if (!mod->enable) {
+            continue;
+        }
+
+        memset(n_opt, 0, sizeof(n_opt));
+        memset(mod_hdr, 0, sizeof(mod_hdr));
+        get_mod_hdr(mod_hdr, mod);
+
+        if (strpbrk(mod->record, ITEM_SPLIT) && MERGE_NOT == conf.print_merge) {
+            n_record = strdup(mod->record);
+            /* set print opt line */
+            token = strtok(n_record, ITEM_SPLIT);
+            int count = 0;
+            mod->p_item = -1;
+            while (token) {
+                s_token = strpbrk(token, ITEM_SPSTART);
+                if (s_token) {
+                    memset(opt, 0, sizeof(opt));
+                    memset(n_opt, 0, sizeof(n_opt));
+                    strncat(opt, token, s_token - token);
+                    if (*mod->print_item != 0 && fnmatch(mod->print_item, opt, 0)) {
+                        token = strtok(NULL, ITEM_SPLIT);
+                        count++;
+                        continue;
+                    }
+                    mod->p_item = count++;
+                    adjust_print_opt_line(n_opt, opt, strlen(mod_hdr));
+                    strcat(opt_line, n_opt);
+                    strcat(opt_line, PRINT_SEC_SPLIT);
+                    strcat(hdr_line, mod_hdr);
+                    strcat(hdr_line, PRINT_SEC_SPLIT);
+                }
+                token = strtok(NULL, ITEM_SPLIT);
+            }
+            free(n_record);
+            n_record = NULL;
+
+        } else {
+            memset(opt, 0, sizeof(opt));
+            /* set print opt line */
+            adjust_print_opt_line(opt, mod->opt_line, strlen(mod_hdr));
+            /* set print hdr line */
+            strcat(hdr_line, mod_hdr);
+            strcat(opt_line, opt);
+        }
+        strcat(hdr_line, PRINT_SEC_SPLIT);
+        strcat(opt_line, PRINT_SEC_SPLIT);
+    }
+
+    sprintf(header, "%s\n%s\n", opt_line, hdr_line);
+    printf("%s", header);
 }
 
 
-void printf_result(double result)
+void
+printf_result(double result)
 {
-	if(conf.print_detail) {
-		printf("%6.2f", result);
-		printf("%s", PRINT_DATA_SPLIT);
-		return;
-	}
-	if ((1000 - result) > 0.1)
-		printf("%6.2f", result);
-	else if ( (1000 - result/1024) > 0.1) {
-		printf("%5.1f%s", result/1024, "K");
-	} else if ((1000 - result/1024/1024) > 0.1) {
-		printf("%5.1f%s", result/1024/1024, "M");
-	} else if ((1000 - result/1024/1024/1024) > 0.1) {
-		printf("%5.1f%s", result/1024/1024/1024, "G");
-	} else if ((1000 - result/1024/1024/1024/1024) > 0.1) {
-		printf("%5.1f%s", result/1024/1024/1024/1024, "T");
-	}
-	printf("%s", PRINT_DATA_SPLIT);
+    if (conf.print_detail) {
+        printf("%6.2f", result);
+        printf("%s", PRINT_DATA_SPLIT);
+        return;
+    }
+
+    if ((1000 - result) > 0.1) {
+        printf("%6.2f", result);
+    } else if ( (1000 - result / 1024) > 0.1) {
+        printf("%5.1f%s", result / 1024, "K");
+    } else if ((1000 - result / 1024 / 1024) > 0.1) {
+        printf("%5.1f%s", result / 1024 / 1024, "M");
+    } else if ((1000 - result / 1024 / 1024 / 1024) > 0.1) {
+        printf("%5.1f%s", result / 1024 / 1024 / 1024, "G");
+    } else if ((1000 - result / 1024 / 1024 / 1024 / 1024) > 0.1) {
+        printf("%5.1f%s", result / 1024 / 1024 / 1024 / 1024, "T");
+    }
+    printf("%s", PRINT_DATA_SPLIT);
 }
 
 
-void print_array_stat(struct module *mod, double *st_array)
+void
+print_array_stat(const struct module *mod, const double *st_array)
 {
-	int i;
-	struct mod_info *info = mod->info;
-
-	for (i=0; i < mod->n_col; i++) {
-		if(mod->spec){
-			/* print null */
-			if (!st_array || !mod->st_flag || st_array[i] < 0) {
-				/* print record */
-				if (((DATA_SUMMARY == conf.print_mode) && (SPEC_BIT == info[i].summary_bit))
-						|| ((DATA_DETAIL == conf.print_mode) && (SPEC_BIT == info[i].summary_bit)))
-					printf("------%s", PRINT_DATA_SPLIT);
-			} else {
-				/* print record */
-				if (((DATA_SUMMARY == conf.print_mode) && (SPEC_BIT == info[i].summary_bit))
-						|| ((DATA_DETAIL == conf.print_mode) && (SPEC_BIT == info[i].summary_bit)))
-					printf_result(st_array[i]);
-			}
-
-		}
-		else {
-			/* print null */
-			if (!st_array || !mod->st_flag || st_array[i] < 0) {
-				/* print record */
-				if (((DATA_SUMMARY == conf.print_mode) && (SUMMARY_BIT == info[i].summary_bit))
-						|| ((DATA_DETAIL == conf.print_mode) && (HIDE_BIT != info[i].summary_bit)))
-					printf("------%s", PRINT_DATA_SPLIT);
-			} else {
-				/* print record */
-				if (((DATA_SUMMARY == conf.print_mode) && (SUMMARY_BIT == info[i].summary_bit))
-						|| ((DATA_DETAIL == conf.print_mode) && (HIDE_BIT != info[i].summary_bit)))
-					printf_result(st_array[i]);
-			}
-		}
-	}
+    int    i;
+    struct mod_info *info = mod->info;
+
+    for (i = 0; i < mod->n_col; i++) {
+        if (mod->spec) {
+            /* print null */
+            if (!st_array || !mod->st_flag || st_array[i] < 0) {
+                /* print record */
+                if (((DATA_SUMMARY == conf.print_mode) && (SPEC_BIT == info[i].summary_bit))
+                        || ((DATA_DETAIL == conf.print_mode) && (SPEC_BIT == info[i].summary_bit)))
+                {
+                    printf("------%s", PRINT_DATA_SPLIT);
+                }
+
+            } else {
+                /* print record */
+                if (((DATA_SUMMARY == conf.print_mode) && (SPEC_BIT == info[i].summary_bit))
+                        || ((DATA_DETAIL == conf.print_mode) && (SPEC_BIT == info[i].summary_bit)))
+                {
+                    printf_result(st_array[i]);
+                }
+            }
+
+        } else {
+            /* print null */
+            if (!st_array || !mod->st_flag || st_array[i] < 0) {
+                /* print record */
+                if (((DATA_SUMMARY == conf.print_mode) && (SUMMARY_BIT == info[i].summary_bit))
+                        || ((DATA_DETAIL == conf.print_mode) && (HIDE_BIT != info[i].summary_bit)))
+                {
+                    printf("------%s", PRINT_DATA_SPLIT);
+                }
+
+            } else {
+                /* print record */
+                if (((DATA_SUMMARY == conf.print_mode) && (SUMMARY_BIT == info[i].summary_bit))
+                        || ((DATA_DETAIL == conf.print_mode) && (HIDE_BIT != info[i].summary_bit)))
+                {
+                    printf_result(st_array[i]);
+                }
+            }
+        }
+    }
 }
 
 
 /* print current time */
-void print_current_time()
+void
+print_current_time()
 {
-	char cur_time[LEN_32] = {0};
-	time_t timep;
-	struct tm *t;
-
-	time(&timep);
-	t = localtime(&timep);
-	if(conf.running_mode == RUN_PRINT_LIVE)
-		strftime(cur_time, sizeof(cur_time), "%d/%m/%y-%T", t);
-	else
-		strftime(cur_time, sizeof(cur_time), "%d/%m/%y-%R", t);
-	printf("%s%s", cur_time, PRINT_SEC_SPLIT);
+    char    cur_time[LEN_32] = {0};
+    time_t  timep;
+    struct  tm *t;
+
+    time(&timep);
+    t = localtime(&timep);
+    if (conf.running_mode == RUN_PRINT_LIVE) {
+        strftime(cur_time, sizeof(cur_time), "%d/%m/%y-%T", t);
+
+    } else {
+        strftime(cur_time, sizeof(cur_time), "%d/%m/%y-%R", t);
+    }
+    printf("%s%s", cur_time, PRINT_SEC_SPLIT);
 }
 
 
-void print_record()
+void
+print_record()
 {
-	struct module *mod = NULL;
-	int  i, j;
-	double *st_array;
-
-	/* print summary data */
-	for (i = 0; i < statis.total_mod_num; i++) {
-		mod = &mods[i];
-		if (!mod->enable)				
-			continue;
-
-		if (!mod->n_item) {
-			print_array_stat(mod, NULL);
-			printf("%s", PRINT_SEC_SPLIT);
-
-		} else {
-			for (j = 0; j < mod->n_item; j++) {
-				st_array = &mod->st_array[j * mod->n_col];
-				print_array_stat(mod, st_array);
-				printf("%s", PRINT_SEC_SPLIT);
-			}
-			if (mod->n_item > 1)
-				printf("%s", PRINT_SEC_SPLIT);
-		}
-	}
-	printf("\n");
+    int        i, j;
+    double    *st_array;
+    struct     module *mod = NULL;
+
+    /* print summary data */
+    for (i = 0; i < statis.total_mod_num; i++) {
+        mod = mods[i];
+        if (!mod->enable) {
+            continue;
+        }
+        if (!mod->n_item) {
+            print_array_stat(mod, NULL);
+            printf("%s", PRINT_SEC_SPLIT);
+
+        } else {
+            for (j = 0; j < mod->n_item; j++) {
+                if (*mod->print_item != 0 && (mod->p_item != j)) {
+                    continue;
+                }
+                st_array = &mod->st_array[j * mod->n_col];
+                print_array_stat(mod, st_array);
+                printf("%s", PRINT_SEC_SPLIT);
+            }
+            if (mod->n_item > 1) {
+                printf("%s", PRINT_SEC_SPLIT);
+            }
+        }
+    }
+    printf("\n");
 }
 
 
 /* running in print live mode */
-void running_print_live()
+void
+running_print_live()
 {
-	int print_num = 1, re_p_hdr = 0;
-
-	collect_record();
-
-	/* print header */
-	print_header();
-
-	/* set struct module fields */
-	init_module_fields();
-
-	/* skip first record */
-	if(collect_record_stat() == 0)
-		do_debug(LOG_INFO, "collect_record_stat warn\n");
-	sleep(conf.print_interval);
-
-	/* print live record */
-	while (1) {
-		collect_record();
-
-		if (!((print_num) % DEFAULT_PRINT_NUM) || re_p_hdr) {
-			/* get the header will print every DEFAULT_PRINT_NUM */
-			print_header();
-			re_p_hdr = 0;
-			print_num = 1;
-		}
-
-		if (!collect_record_stat()) {
-			re_p_hdr = 1;
-			continue;
-		}
-
-		/* print current time */
-		print_current_time();
-		print_record();
-
-		print_num++;
-		/* sleep every interval */
-		sleep(conf.print_interval);
-	}
+    int print_num = 1, re_p_hdr = 0, cost_time = 0, to_sleep = 0;
+
+    struct timeval tv_begin, tv_end;
+    gettimeofday(&tv_begin, NULL);
+    collect_record();
+
+    /* print header */
+    print_header();
+
+    /* set struct module fields */
+    init_module_fields();
+
+    /* skip first record */
+    if (collect_record_stat() == 0) {
+        do_debug(LOG_INFO, "collect_record_stat warn\n");
+    }
+    gettimeofday(&tv_end, NULL);
+    cost_time = (tv_end.tv_sec - tv_begin.tv_sec)*1000000 + (tv_end.tv_usec - tv_begin.tv_usec);
+    to_sleep = conf.print_interval*1000000 - cost_time;
+    if (to_sleep > 0) {
+      usleep(to_sleep);
+    }
+
+    /* print live record */
+    while (1) {
+        gettimeofday(&tv_begin, NULL);
+        collect_record();
+
+        if (!((print_num) % DEFAULT_PRINT_NUM) || re_p_hdr) {
+            /* get the header will print every DEFAULT_PRINT_NUM */
+            print_header();
+            re_p_hdr = 0;
+            print_num = 1;
+        }
+
+        if (!collect_record_stat()) {
+            re_p_hdr = 1;
+            continue;
+        }
+
+        /* print current time */
+        print_current_time();
+        print_record();
+        fflush(stdout);
+
+        print_num++;
+
+        /* sleep every interval */
+        gettimeofday(&tv_end, NULL);
+        cost_time = (tv_end.tv_sec - tv_begin.tv_sec)*1000000 + (tv_end.tv_usec - tv_begin.tv_usec);
+        to_sleep = conf.print_interval*1000000 - cost_time;
+        if (to_sleep > 0) {
+          usleep(to_sleep);
+        }
+    }
 }
 
 
 
 /* find where start printting
-   返回值：
-   0 查找成功
-   1 需要再往上一个文件查询
-   2 查找失败，发生在对tsar.data.x查找时，要找的时间比该文件的最晚时间还晚，此时说明查找落在了轮转期的数据丢失部分，不应再继续查找，
-   3 查找失败，发生在对tsar.data查找时，说明tsar已经有一段时间没有运行，从要查找的时间点到现在都没有数据，不应再继续查找
-   4 查找失败，发生的场景是，tsar中间有段时间没有采集数据，而要查找的时间点正好又落在这个区间，不应再继续查找
-   5 查找过程中碰到日志格式错误
-   6 未知错误*/
-int find_offset_from_start(FILE *fp,int number)
+ * number:the suffix number of record data (tsar.data.number)
+ * return
+ * 0 ok
+ * 1 need find last tsar.data file
+ * 2 find error, find time is later than the last line at tsar.data.x, should stop find any more
+ * 3 find error, tsar haved stopped after find time, should stop find it
+ * 4 find error, data not exist, tsar just lost some time data which contains find time
+ * 5 log format error
+ * 6 other error
+ */
+int
+find_offset_from_start(FILE *fp, int number)
 {
-	char	line[LEN_10240] = {0};
-	long	fset, fend, file_len, off_start, off_end, offset, line_len;
-	char	*p_sec_token;
-	time_t	now, t_token, t_get;
-	struct tm stm;
-
-	/* get file len */
-	fseek(fp, 0, SEEK_END);
-	fend = ftell(fp);
-	fseek(fp, 0, SEEK_SET);
-	fset = ftell(fp);
-	file_len = fend - fset;
-
-	memset(&line, 0, LEN_10240);
-	fgets(line, LEN_10240, fp);
-	line_len = strlen(line);
-
-	/* get time token */
-	time(&now);
-	if(conf.print_day > 180){
-		/*get specify date by --date/-d*/
-		stm.tm_year = conf.print_day / 10000 - 1900;
-		stm.tm_mon = conf.print_day % 10000 / 100 - 1;
-		stm.tm_mday = conf.print_day % 100;
-		t_token = mktime(&stm);
-		conf.print_day = (now - t_token) / (24 * 60 * 60);
-	}
-	if(conf.print_day >= 0){
-		if(conf.print_day > 180)
-			conf.print_day = 180;
-		/* get day's beginning plus 8 hours.Set start and end time for print*/
-		now = now - now % (24 * 60 * 60) - (8 * 60 * 60);
-		t_token = now - conf.print_day * (24 * 60 * 60) - (60 * conf.print_nline_interval);
-		conf.print_start_time = t_token;
-		conf.print_end_time = t_token + 24 * 60 * 60 + (60 * conf.print_nline_interval);
-	}else{
-		/* set max days for print 6 months*/
-		if(conf.print_ndays > 180)
-			conf.print_ndays = 180;
-		now = now - now % (60 * conf.print_nline_interval);
-		t_token = now - conf.print_ndays * (24 * 60 * 60) - (60 * conf.print_nline_interval);
-		conf.print_start_time = t_token;
-		conf.print_end_time = now + (60 * conf.print_nline_interval);
-	}
-
-	offset = off_start = 0;
-	off_end = file_len;
-	while (1) {
-		offset = (off_start + off_end)/2;
-		memset(&line, 0, LEN_10240);
-		fseek(fp, offset, SEEK_SET);
-		fgets(line, LEN_10240, fp);
-		memset(&line, 0, LEN_10240);
-		fgets(line, LEN_10240, fp);
-		if (0 != line[0] && offset > line_len) {
-			p_sec_token = strstr(line, SECTION_SPLIT);
-			if (p_sec_token) {
-				*p_sec_token = '\0';
-				t_get = atol(line);
-				if (abs(t_get - t_token) <= 60) {
-					conf.print_file_number = number;
-					return 0;
-				}
-
-				/* Binary Search */
-				if (t_get > t_token) {
-					off_end = offset;
-				}
-				else if (t_get < t_token) {
-					off_start = offset;
-				}
-			}
-			else {
-				//fatal error,log format error happen.
-				return 5;
-			}
-		}
-		else {
-			if(off_end == file_len){
-				if(number>0){
-					conf.print_file_number = number-1;
-					//at the end of tsar.data.%d have some data lost during data rotate. stat from previous log file";
-					return 2;
-				} else{
-					//researching tsar.data to end and not find log data you need.";
-					return 3;
-				}
-			}
-			if(off_start == 0){
-				conf.print_file_number = number;
-				//need to research tsar.data.number+1;
-				return 1;
-			}
-			//here should not be arrived.
-			return 6;
-		}
-
-		if (offset == (off_start + off_end)/2){
-			if(off_start != 0){
-				//tsar has been down for a while,so,the following time's stat we can provied only;
-				conf.print_file_number = number;
-				return 4;
-			}
-			return 6;
-		}
-	}
+    long        fset, fend, file_len, off_start, off_end, offset, line_len;
+    char       *p_sec_token;
+    time_t      now, t_token, t_get;
+    struct tm   stm;
+    static char line[LEN_10M] = {0};
+
+    /* get file len */
+    if (fseek(fp, 0, SEEK_END) != 0 ) {
+        do_debug(LOG_FATAL, "fseek error:%s", strerror(errno));
+    }
+    if ((fend = ftell(fp)) < 0) {
+        do_debug(LOG_FATAL, "ftell error:%s", strerror(errno));
+    }
+    if (fseek(fp, 0, SEEK_SET) != 0) {
+        do_debug(LOG_FATAL, "fseek error:%s", strerror(errno));
+    }
+    if ((fset = ftell(fp)) < 0) {
+        do_debug(LOG_FATAL, "ftell error:%s", strerror(errno));
+    }
+    file_len = fend - fset;
+
+    memset(&line, 0, LEN_10M);
+    if (!fgets(line, LEN_10M, fp)) {
+        do_debug(LOG_FATAL, "fgets error:%s", strerror(errno));
+    }
+    line_len = strlen(line);
+
+    /* get time token */
+    time(&now);
+    if (conf.print_day > conf.print_max_day) {
+        /*get specify date by --date/-d*/
+        stm.tm_year = conf.print_day / 10000 - 1900;
+        stm.tm_mon = conf.print_day % 10000 / 100 - 1;
+        stm.tm_mday = conf.print_day % 100;
+        stm.tm_hour = 0;
+        stm.tm_min = 0;
+        stm.tm_sec = 0;
+        stm.tm_isdst = -1;
+        t_token = mktime(&stm);
+        conf.print_day = (now - t_token) / (24 * 60 * 60);
+    }
+
+    if (conf.print_day >= 0) {
+        if (conf.print_day > conf.print_max_day) {
+            conf.print_day = conf.print_max_day;
+        }
+        /* get day's beginning plus 8 hours.Set start and end time for print*/
+        now = now - now % (24 * 60 * 60) - (8 * 60 * 60);
+        t_token = now - conf.print_day * (24 * 60 * 60) - (60 * conf.print_nline_interval);
+        conf.print_start_time = t_token;
+        conf.print_end_time = t_token + 24 * 60 * 60 + (60 * conf.print_nline_interval);
+
+    } else {
+        /* set max days for print 6 months*/
+        if (conf.print_ndays > conf.print_max_day) {
+            conf.print_ndays = conf.print_max_day;
+        }
+        now = now - now % (60 * conf.print_nline_interval);
+        if (conf.running_mode == RUN_WATCH) {
+            if (conf.print_nminute > (conf.print_max_day * 24 * 60)) {
+                conf.print_nminute = conf.print_max_day * 24 * 60;
+            }
+            t_token = now - (60 * conf.print_nminute) - (60 * conf.print_nline_interval);
+        } else {
+            t_token = now - conf.print_ndays * (24 * 60 * 60) - (60 * conf.print_nline_interval);
+        }
+        conf.print_start_time = t_token;
+        conf.print_end_time = now + (60 * conf.print_nline_interval);
+    }
+
+    offset = off_start = 0;
+    off_end = file_len;
+    while (1) {
+        offset = (off_start + off_end) / 2;
+        memset(&line, 0, LEN_10M);
+        if (fseek(fp, offset, SEEK_SET) != 0) {
+            do_debug(LOG_FATAL, "fseek error:%s", strerror(errno));
+        }
+        if (!fgets(line, LEN_10M, fp) && errno != 0) {
+            do_debug(LOG_FATAL, "fgets error:%s", strerror(errno));
+        }
+        memset(&line, 0, LEN_10M);
+        if (!fgets(line, LEN_10M, fp) && errno != 0) {
+            do_debug(LOG_FATAL, "fgets error:%s", strerror(errno));
+        }
+        if (0 != line[0] && offset > line_len) {
+            p_sec_token = strpbrk(line, SECTION_SPLIT);
+            if (p_sec_token) {
+                *p_sec_token = '\0';
+                t_get = atol(line);
+                if (labs(t_get - t_token) <= 60) {
+                    conf.print_file_number = number;
+                    return 0;
+                }
+
+                /* Binary Search */
+                if (t_get > t_token) {
+                    off_end = offset;
+
+                } else if (t_get < t_token) {
+                    off_start = offset;
+                }
+
+            } else {
+                /* fatal error, log format error happen. */
+                return 5;
+            }
+
+        } else {
+            if (off_end == file_len) {
+                if (number > 0) {
+                    conf.print_file_number = number - 1;
+                    /* at the end of tsar.data.%d have some data lost during data rotate. stat from previous log file";*/
+                    return 2;
+
+                } else {
+                    /* researching tsar.data to end and not find log data you need.";*/
+                    return 3;
+                }
+            }
+            if (off_start == 0) {
+                conf.print_file_number = number;
+                /* need to research tsar.data.number+1; */
+                return 1;
+            }
+            /* here should not be arrived. */
+            return 6;
+        }
+
+        if (offset == (off_start + off_end) / 2) {
+            if (off_start != 0) {
+                /* tsar has been down for a while, so the following time's stat we can provied only; */
+                conf.print_file_number = number;
+                return 4;
+            }
+            return 6;
+        }
+    }
 }
 
 
 /*
  * set and print record time
  */
-long set_record_time(char *line)
+long
+set_record_time(const char *line)
 {
-	char *token, s_time[LEN_32] = {0};
-	static long pre_time, c_time = 0;
-
-	/* get record time */
-	token = strstr(line, SECTION_SPLIT);
-	memcpy(s_time, line, token - line);
-
-	/* swap time */
-	pre_time = c_time;
-	c_time = atol(s_time);
-
-	c_time = c_time - c_time%60;
-	pre_time = pre_time - pre_time%60;
-	/* if skip record when two lines haveing same minute */
-	if (!(conf.print_interval = c_time - pre_time))
-		return 0;
-	else
-		return c_time;
+    char        *token, s_time[LEN_32] = {0};
+    static long  pre_time, c_time = 0;
+
+    /* get record time */
+    token = strpbrk(line, SECTION_SPLIT);
+    memcpy(s_time, line, token - line);
+
+    /* swap time */
+    pre_time = c_time;
+    c_time = atol(s_time);
+
+    c_time = c_time - c_time % 60;
+    pre_time = pre_time - pre_time % 60;
+    /* if skip record when two lines haveing same minute */
+    if (!(conf.print_interval = c_time - pre_time)) {
+        return 0;
+
+    } else {
+        return c_time;
+    }
 }
 
-/* 
- * check time if corret for pirnt from tsar.data 
+/*
+ * check time if corret for pirnt from tsar.data
  */
-int check_time(char *line)
+int
+check_time(const char *line)
 {
-	char *token, s_time[LEN_32] = {0};
-	long now_time = 0;
-	static long pre_time;
-
-	/* get record time */
-	token = strstr(line, SECTION_SPLIT);
-	memcpy(s_time, line, token - line);
-	now_time = atol(s_time);
-
-	/* check if time is over print_end_time */
-	if(now_time >= conf.print_end_time)
-		return 3;
-	/* if time is divide by conf.print_nline_interval*/
-	now_time = now_time - now_time % 60;
-	if (!((now_time - conf.print_start_time) % ( 60 * conf.print_nline_interval)) && now_time > pre_time){
-		/* check  now and last record time interval */
-		if(pre_time && now_time - pre_time == ( 60 * conf.print_nline_interval)){
-			pre_time = now_time;
-			return 0;
-		}
-		pre_time = now_time;
-		return 1;
-	}
-	else
-		return 1;
+    char       *token, s_time[LEN_32] = {0};
+    long        now_time = 0;
+    static long pre_time;
+
+    /* get record time */
+    token = strpbrk(line, SECTION_SPLIT);
+    if (token == NULL) {
+        return 1;
+    }
+    if ((token - line) < 32) {
+        memcpy(s_time, line, token - line);
+    }
+    now_time = atol(s_time);
+
+    /* check if time is over print_end_time */
+    if (now_time >= conf.print_end_time) {
+        return 3;
+    }
+    /* if time is divide by conf.print_nline_interval*/
+    now_time = now_time - now_time % 60;
+    if (!((now_time - conf.print_start_time) % ( 60 * conf.print_nline_interval)) && now_time > pre_time) {
+        /* check  now and last record time interval */
+        if (pre_time && now_time - pre_time == ( 60 * conf.print_nline_interval)) {
+            pre_time = now_time;
+            return 0;
+        }
+        pre_time = now_time;
+        return 1;
+
+    } else {
+        return 1;
+    }
 }
 
-void print_record_time(long c_time)
+void
+print_record_time(long c_time)
 {
-	char s_time[LEN_32] = {0};
-	struct tm *t;
+    char    s_time[LEN_32] = {0};
+    struct  tm *t;
 
-	t = localtime(&c_time);
-	strftime(s_time, sizeof(s_time), "%d/%m/%y-%R", t);
-	printf("%s%s", s_time, PRINT_SEC_SPLIT);
+    t = localtime(&c_time);
+    strftime(s_time, sizeof(s_time), "%d/%m/%y-%R", t);
+    printf("%s%s", s_time, PRINT_SEC_SPLIT);
 }
 
 
-void print_tail(int tail_type)
+void
+print_tail(int tail_type)
 {
-	struct module *mod = NULL;
-	int  i, j, k;
-	double *m_tail;
-
-	switch (tail_type) {
-		case TAIL_MAX:
-			printf("MAX           %s", PRINT_SEC_SPLIT);
-			break;
-		case TAIL_MEAN:
-			printf("MEAN          %s", PRINT_SEC_SPLIT);
-			break;
-		case TAIL_MIN:
-			printf("MIN           %s", PRINT_SEC_SPLIT);
-			break;
-		default:
-			return;
-	}
-
-	/* print summary data */
-	for (i = 0; i < statis.total_mod_num; i++) {
-		mod = &mods[i];
-		if (!mod->enable)
-			continue;
-		switch (tail_type) {
-			case TAIL_MAX:
-				m_tail = mod->max_array;
-				break;
-			case TAIL_MEAN:
-				m_tail = mod->mean_array;
-				break;
-			case TAIL_MIN:
-				m_tail = mod->min_array;
-				break;
-			default:
-				return;
-		}
-
-		k = 0;
-		for (j = 0; j < mod->n_item; j++) {
-			int i;
-			struct mod_info *info = mod->info;
-			for (i=0; i < mod->n_col; i++) {
-				/* print record */
-				if(mod->spec){
-					if (((DATA_SUMMARY == conf.print_mode) && (SPEC_BIT == info[i].summary_bit))
-							|| ((DATA_DETAIL == conf.print_mode) && (SPEC_BIT == info[i].summary_bit))) {
-						printf_result(m_tail[k]);
-					}
-				}
-				else {
-					if (((DATA_SUMMARY == conf.print_mode) && (SUMMARY_BIT == info[i].summary_bit))
-							|| ((DATA_DETAIL == conf.print_mode) && (HIDE_BIT != info[i].summary_bit))) {
-						printf_result(m_tail[k]);
-					}
-				}
-				k++;
-			}
-			printf("%s", PRINT_SEC_SPLIT);
-		}
-		if (mod->n_item != 1){
-			if(!m_tail){
-				print_array_stat(mod, NULL);
-			}
-			printf("%s", PRINT_SEC_SPLIT);
-		}
-	}
-	printf("\n");
+    int        i, j, k;
+    double    *m_tail;
+    struct     module *mod = NULL;
+
+    switch (tail_type) {
+        case TAIL_MAX:
+            printf("MAX           %s", PRINT_SEC_SPLIT);
+            break;
+        case TAIL_MEAN:
+            printf("MEAN          %s", PRINT_SEC_SPLIT);
+            break;
+        case TAIL_MIN:
+            printf("MIN           %s", PRINT_SEC_SPLIT);
+            break;
+        default:
+            return;
+    }
+
+    /* print summary data */
+    for (i = 0; i < statis.total_mod_num; i++) {
+        mod = mods[i];
+        if (!mod->enable) {
+            continue;
+        }
+        switch (tail_type) {
+            case TAIL_MAX:
+                m_tail = mod->max_array;
+                break;
+            case TAIL_MEAN:
+                m_tail = mod->mean_array;
+                break;
+            case TAIL_MIN:
+                m_tail = mod->min_array;
+                break;
+            default:
+                return;
+        }
+
+        k = 0;
+        for (j = 0; j < mod->n_item; j++) {
+            if (*mod->print_item != 0 && (mod->p_item != j)) {
+                k += mod->n_col;
+                continue;
+            }
+            int    i;
+            struct mod_info *info = mod->info;
+            for (i=0; i < mod->n_col; i++) {
+                /* print record */
+                if (mod->spec) {
+                    if (((DATA_SUMMARY == conf.print_mode) && (SPEC_BIT == info[i].summary_bit))
+                            || ((DATA_DETAIL == conf.print_mode) && (SPEC_BIT == info[i].summary_bit)))
+                    {
+                        printf_result(m_tail[k]);
+                    }
+
+                } else {
+                    if (((DATA_SUMMARY == conf.print_mode) && (SUMMARY_BIT == info[i].summary_bit))
+                            || ((DATA_DETAIL == conf.print_mode) && (HIDE_BIT != info[i].summary_bit)))
+                    {
+                        printf_result(m_tail[k]);
+                    }
+                }
+                k++;
+            }
+            printf("%s", PRINT_SEC_SPLIT);
+        }
+        if (mod->n_item != 1) {
+            if (!m_tail) {
+                print_array_stat(mod, NULL);
+            }
+            printf("%s", PRINT_SEC_SPLIT);
+        }
+    }
+    printf("\n");
 }
 
 
 /*
  * init_running_print, if sucess then return fp, else return NULL
  */
-FILE *init_running_print()
+FILE *
+init_running_print()
 {
-	int	i=0,k=0;
-	FILE	*fp,*fptmp;
-	char	line[LEN_10240] = {0};
-	char	filename[LEN_128] = {0};
-
-	/* will print tail*/
-	conf.print_tail = 1;
-
-	fp = fopen(conf.output_file_path, "r");
-	if (!fp){
-		do_debug(LOG_FATAL, "unable to open the log file %s\n",conf.output_file_path);
-	}
-	/*log number to use for print*/
-	conf.print_file_number = -1;
-	/* find start offset will print from tsar.data */
-	k=find_offset_from_start(fp,i);
-	if(k==1){
-		/*find all possible record*/
-		for(i=1;;i++){
-			memset(filename,0,sizeof(filename));
-			sprintf(filename,"%s.%d",conf.output_file_path,i);
-			fptmp = fopen(filename, "r");
-			if(!fptmp){
-				conf.print_file_number = i - 1;
-				break;
-			}
-
-			k=find_offset_from_start(fptmp,i);
-			if(k==0 || k==4){
-				fclose(fp);
-				fp=fptmp;
-				break;
-			}
-			if(k==2){
-				fseek(fp,0,SEEK_SET);
-				fclose(fptmp);
-				break;
-			}
-			if(k==1){
-				fclose(fp);
-				fp=fptmp;
-				continue;
-			}
-			if(k==5 || k==6){
-				do_debug(LOG_FATAL, "log format error or find_offset_from_start have a bug. error code=%d\n",k);
-			}
-		}
-	}
-
-	if(k==5 || k==6){
-		do_debug(LOG_FATAL, "log format error or find_offset_from_start have a bug. error code=%d\n",k);
-	}
-	/* get record */
-	if (!fgets(line, LEN_10240, fp)) {
-		do_debug(LOG_FATAL, "can't get enough log info\n");
-	}
-
-	/* read one line to init module parameter */
-	read_line_to_module_record(line);
-
-	/* print header */
-	print_header();
-
-	/* set struct module fields */	
-	init_module_fields();
-
-	set_record_time(line);
-	return fp;
+    int           i=0, k=0;
+    FILE         *fp, *fptmp;
+    char          filename[LEN_128] = {0};
+    static char   line[LEN_10M] = {0};
+
+    /* will print tail*/
+    conf.print_tail = 1;
+
+    fp = fopen(conf.output_file_path, "r");
+    if (!fp) {
+        do_debug(LOG_FATAL, "unable to open the log file %s\n", conf.output_file_path);
+    }
+    /*log number to use for print*/
+    conf.print_file_number = -1;
+    /* find start offset will print from tsar.data */
+    k=find_offset_from_start(fp, i);
+    if (k == 1) {
+        /*find all possible record*/
+        for (i=1; ; i++) {
+            memset(filename, 0, sizeof(filename));
+            sprintf(filename, "%s.%d", conf.output_file_path, i);
+            fptmp = fopen(filename, "r");
+            if (!fptmp) {
+                conf.print_file_number = i - 1;
+                break;
+            }
+
+            k=find_offset_from_start(fptmp, i);
+            if (k==0 || k==4) {
+                if (fclose(fp) < 0) {
+                    do_debug(LOG_FATAL, "fclose error:%s", strerror(errno));
+                }
+                fp=fptmp;
+                break;
+            }
+            if (k== 2) {
+                if (fseek(fp, 0, SEEK_SET) != 0) {
+                    do_debug(LOG_FATAL, "fseek error:%s", strerror(errno));
+                }
+                if (fclose(fptmp) < 0) {
+                    do_debug(LOG_FATAL, "fclose error:%s", strerror(errno));
+                }
+                break;
+            }
+            if (k == 1) {
+                if (fclose(fp) < 0) {
+                    do_debug(LOG_FATAL, "fclose error:%s", strerror(errno));
+                }
+                fp=fptmp;
+                continue;
+            }
+            if (k == 5 || k == 6) {
+                do_debug(LOG_FATAL, "log format error or find_offset_from_start have a bug. error code=%d\n", k);
+            }
+        }
+    }
+
+    if (k == 5 || k == 6) {
+        do_debug(LOG_FATAL, "log format error or find_offset_from_start have a bug. error code=%d\n", k);
+    }
+    /* get record */
+    if (!fgets(line, LEN_10M, fp)) {
+        do_debug(LOG_FATAL, "can't get enough log info\n");
+    }
+
+    /* read one line to init module parameter */
+    read_line_to_module_record(line);
+
+    /* print header */
+    print_header();
+
+    /* set struct module fields */
+    init_module_fields();
+
+    set_record_time(line);
+    return fp;
 }
 
 
 /*
  * print mode, print data from tsar.data
  */
-void running_print()
+void
+running_print()
 {
-	char	line[LEN_10240] = {0};
-	char	filename[LEN_128] = {0};
-	int	print_num = 1, re_p_hdr = 0;
-	long	n_record = 0, s_time;
-	FILE	*fp;
-
-	fp = init_running_print();
-
-	/* skip first record */
-	if(collect_record_stat() ==0)
-		do_debug(LOG_INFO, "collect_record_stat warn\n");
-	while (1) {
-		if(!fgets(line, LEN_10240, fp)){
-			if(conf.print_file_number <= 0)
-				break;
-			else{
-				conf.print_file_number = conf.print_file_number - 1;
-				memset(filename,0,sizeof(filename));
-				if(conf.print_file_number == 0)
-					sprintf(filename,"%s",conf.output_file_path);
-				else
-					sprintf(filename,"%s.%d",conf.output_file_path,conf.print_file_number);
-				fclose(fp);
-				fp = fopen(filename,"r");
-				if(!fp){
-					do_debug(LOG_FATAL, "unable to open the log file %s.\n",filename);
-				}
-				continue;
-			}
-		}
-
-		int k =check_time(line);
-		if(k == 1){
-			continue;
-		}
-		if(k == 3){
-			break;
-		}
-
-		/* collect data then set mod->summary */
-		read_line_to_module_record(line);
-
-		if (!(print_num % DEFAULT_PRINT_NUM) || re_p_hdr) {
-			/* get the header will print every DEFAULT_PRINT_NUM */
-			print_header();
-			re_p_hdr = 0;
-			print_num = 1;
-		}
-
-		/* exclued the two record have same time */
-		if (!(s_time = set_record_time(line)))
-			continue;
-
-		/* reprint header because of n_item's modifing */
-		if (!collect_record_stat()) {
-			re_p_hdr = 1;
-			continue;
-		}
-
-		print_record_time(s_time);
-		print_record();
-		n_record++;
-		print_num++;
-		memset(line, 0, sizeof(line));
-	}
-
-	if (n_record) {
-		printf("\n");
-		print_tail(TAIL_MAX);
-		print_tail(TAIL_MEAN);
-		print_tail(TAIL_MIN);
-	}
-
-	fclose(fp);
-	fp = NULL;
+    int           print_num = 1, re_p_hdr = 0;
+    char          filename[LEN_128] = {0};
+    long          n_record = 0, s_time;
+    FILE         *fp;
+    static char   line[LEN_10M] = {0};
+
+    /*find the position of the first record to be printed. (eg: middle of tsar.data.2)*/
+    fp = init_running_print();
+
+    /* skip first record */
+    if (collect_record_stat() == 0) {
+        do_debug(LOG_INFO, "collect_record_stat warn\n");
+    }
+
+    /*now ,print all printable records*/
+    /*(eg: second half of tsar.data.2, then all of tsar.data.1, then tsar.data)*/
+    while (1) {
+        if (!fgets(line, LEN_10M, fp)) {
+            if (conf.print_file_number <= 0) {
+                break;
+
+            } else {
+                conf.print_file_number = conf.print_file_number - 1;
+                memset(filename, 0, sizeof(filename));
+                if (conf.print_file_number == 0) {
+                    sprintf(filename, "%s", conf.output_file_path);
+
+                } else {
+                    sprintf(filename, "%s.%d", conf.output_file_path, conf.print_file_number);
+                }
+                if (fclose(fp) < 0) {
+                    do_debug(LOG_FATAL, "fclose error:%s", strerror(errno));
+                }
+                fp = fopen(filename, "r");
+                if (!fp) {
+                    do_debug(LOG_FATAL, "unable to open the log file %s.\n", filename);
+                }
+                continue;
+            }
+        }
+
+        int    k = check_time(line);
+        if (k == 1) {
+            continue;
+        }
+        if (k == 3) {
+            break;
+        }
+
+        /* collect data then set mod->summary */
+        read_line_to_module_record(line);
+
+        if (!(print_num % DEFAULT_PRINT_NUM) || re_p_hdr) {
+            /* get the header will print every DEFAULT_PRINT_NUM */
+            print_header();
+            re_p_hdr = 0;
+            print_num = 1;
+        }
+
+        /* exclued the two record have same time */
+        if (!(s_time = set_record_time(line))) {
+            continue;
+        }
+
+        /* reprint header because of n_item's modifing */
+        if (!collect_record_stat()) {
+            re_p_hdr = 1;
+            continue;
+        }
+
+        print_record_time(s_time);
+        print_record();
+        n_record++;
+        print_num++;
+        memset(line, 0, sizeof(line));
+    }
+
+    if (n_record) {
+        printf("\n");
+        print_tail(TAIL_MAX);
+        print_tail(TAIL_MEAN);
+        print_tail(TAIL_MIN);
+    }
+
+    if (fclose(fp) < 0) {
+        do_debug(LOG_FATAL, "fclose error:%s", strerror(errno));
+    }
+    fp = NULL;
 }
 
-char* trim(char* src,int max_len){
-	int cur_len = 0;
-	char *index=src;
-	while(*index == ' ' && cur_len<max_len){
-		index++;
-		cur_len++;
-	}
-	return index;
+char *
+trim(char* src, int max_len)
+{
+    int    cur_len = 0;
+    char  *index=src;
+
+    while (*index == ' ' && cur_len<max_len) {
+        index++;
+        cur_len++;
+    }
+    return index;
 }
 
-void running_check(int check_type){
-	char	line[2][LEN_10240];
-	char	filename[LEN_128] = {0};
-	FILE	*fp;
-	int	total_num=0,i,j,k;
-	struct  module *mod = NULL;
-	double  *st_array;
-	char    tmp[9][LEN_256];
-	char    check[LEN_10240] = {0};
-	char    host_name[LEN_64] = {0};
-
-	/* get hostname */
-	if (0 != gethostname(host_name, sizeof(host_name))) {
-		do_debug(LOG_FATAL, "tsar -check: gethostname err, errno=%d", errno);
-	}
-	i = 0;
-	while (host_name[i]) {
-		if (!isprint(host_name[i++])) {
-			host_name[i-1] = '\0';
-			break;
-		}
-	}
-	sprintf(check,"%s\ttsar\t",host_name);
-	sprintf(filename,"%s",conf.output_file_path);
-	fp = fopen(filename,"r");
-	if(!fp){
-		do_debug(LOG_FATAL, "unable to open the log file %s.\n",filename);
-	}
-	/* get file len */
-	memset(&line[0], 0, LEN_10240);
-	total_num =0;
-	//从后往前快速找到2个换行
-	fseek(fp, -1, SEEK_END);
-	while(1){
-		if(fgetc(fp) == '\n') ++total_num;
-		if(total_num == 3) break;
-		if(fseek(fp, -2, SEEK_CUR) != 0){
-			//只有1行或者2行数据，直接重定向到文件头
-			fseek(fp, 0, SEEK_SET);
-			break;
-		}
-	}
-	/*FIX ME*/
-	if(total_num == 0){
-		fclose(fp);
-		memset(filename,0,sizeof(filename));
-		sprintf(filename,"%s.1",conf.output_file_path);
-		fp = fopen(filename,"r");
-		if(!fp){
-			do_debug(LOG_FATAL, "unable to open the log file %s.\n",filename);
-		}
-		total_num = 0;
-		memset(&line[0], 0, 2 * LEN_10240);
-		//tsar.data.1的行数统计
-		fseek(fp, -1, SEEK_END);
-		while(1){
-			if(fgetc(fp) == '\n') ++total_num;
-			if(total_num == 3) break;
-			if(fseek(fp, -2, SEEK_CUR) != 0){
-				fseek(fp, 0, SEEK_SET);
-				break;
-			}
-		}
-		if(total_num < 2){
-			do_debug(LOG_FATAL, "not enough lines at log file %s.\n",filename);
-		}
-
-		memset(&line[0], 0, LEN_10240);
-		fgets(line[0], LEN_10240, fp);
-		memset(&line[1], 0, LEN_10240);
-		fgets(line[1], LEN_10240, fp);
-
-	}else if(total_num == 1){
-		memset(&line[1], 0, LEN_10240);
-		fgets(line[1], LEN_10240, fp);
-		fclose(fp);
-		sprintf(filename,"%s.1",conf.output_file_path);
-		fp = fopen(filename,"r");
-		if(!fp){
-			do_debug(LOG_FATAL, "unable to open the log file %s\n",filename);
-		}
-		total_num = 0;
-		//定位tsar.data.1的最后一行开头
-		fseek(fp, -1, SEEK_END);
-		while(1){
-			if(fgetc(fp) == '\n') ++total_num;
-			//找到倒数第二个换行，读指针刚好指向倒数第一行
-			if(total_num == 2) break;
-			if(fseek(fp, -2, SEEK_CUR) != 0){
-				fseek(fp, 0, SEEK_SET);
-				break;
-			}
-		}
-
-		if(total_num < 1){
-			do_debug(LOG_FATAL, "not enough lines at log file %s\n",filename);
-		}
-		memset(&line[0], 0, LEN_10240);
-		fgets(line[0], LEN_10240, fp);
-	}else{
-		memset(&line[0], 0, LEN_10240);
-		fgets(line[0], LEN_10240, fp);
-		memset(&line[1], 0, LEN_10240);
-		fgets(line[1], LEN_10240, fp);
-	}
-	/* set struct module fields */  
-	init_module_fields();
-
-	//printf("%s",line);
-	/* read one line to init module parameter */
-	read_line_to_module_record(line[0]);
-	collect_record_stat();
-
-	//printf("%s",line);
-	read_line_to_module_record(line[1]);
-	collect_record_stat();
-	/*display check detail*/
-	//---------------------------RUN_CHECK_NEW---------------------------------------
-	if(check_type == RUN_CHECK_NEW){
-		printf("%s\ttsar\t",host_name);
-		for (i = 0; i < statis.total_mod_num; i++) {
-			mod = &mods[i];
-			if (!mod->enable){
-				continue;
-			}
-			struct mod_info *info = mod->info;
-			//get mod name
-			char *mod_name = strstr(mod->opt_line,"--");
-			if(mod_name){
-				mod_name += 2;
-			}
-
-			char opt[LEN_128] = {0};
-			char *n_record = strdup(mod->record);
-			char *token = strtok(n_record, ITEM_SPLIT);
-			char *s_token;
-
-			for (j = 0; j < mod->n_item; j++) {
-				memset(opt, 0, sizeof(opt));
-				if(token){
-					s_token = strstr(token, ITEM_SPSTART);
-					if(s_token){
-						strncat(opt, token, s_token - token);
-						strcat(opt,":");
-					}
-				}
-				st_array = &mod->st_array[j * mod->n_col];
-				for (k=0; k < mod->n_col; k++) {
-					if(mod->spec){
-						if (!st_array || !mod->st_flag) {
-							if (((DATA_SUMMARY == conf.print_mode) && (SPEC_BIT == info[k].summary_bit))
-									|| ((DATA_DETAIL == conf.print_mode) && (SPEC_BIT == info[k].summary_bit))){
-								printf("%s:%s%s=-%s",mod_name,opt,trim(info[k].hdr,LEN_128), " ");
-							}
-						} else {
-							if (((DATA_SUMMARY == conf.print_mode) && (SPEC_BIT == info[k].summary_bit))
-									|| ((DATA_DETAIL == conf.print_mode) && (SPEC_BIT == info[k].summary_bit))){
-								printf("%s:%s%s=",mod_name,opt,trim(info[k].hdr,LEN_128));
-								//printf_check_result(st_array[k]);
-								printf("%0.1f ",st_array[k]);
-							}
-						}
-					}else{
-						if (!st_array || !mod->st_flag) {
-							if (((DATA_SUMMARY == conf.print_mode) && (SUMMARY_BIT == info[k].summary_bit))
-									|| ((DATA_DETAIL == conf.print_mode) && (HIDE_BIT != info[k].summary_bit))){
-								printf("%s:%s%s=-%s",mod_name,opt,trim(info[k].hdr,LEN_128), " ");
-							}
-						} else {
-							if (((DATA_SUMMARY == conf.print_mode) && (SUMMARY_BIT == info[k].summary_bit))
-									|| ((DATA_DETAIL == conf.print_mode) && (HIDE_BIT != info[k].summary_bit))){
-								printf("%s:%s%s=",mod_name,opt,trim(info[k].hdr,LEN_128));
-								//printf_check_result(st_array[k]);
-								printf("%0.1f ",st_array[k]);
-							}
-						}
-
-					}
-				}
-				if(token){
-					token = strtok(NULL, ITEM_SPLIT);
-				}
-			}
-			if(n_record){
-				free(n_record);
-				n_record = NULL;
-			}
-		}
-		printf("\n");
-		fclose(fp);
-		fp = NULL;
-		return;
-	}
+int
+seek_tail_lines(FILE *fp, int n, int len[])
+{
+    int total_num = 0;
+
+    /* find two \n from end*/
+    if (fseek(fp, -1, SEEK_END) != 0) {
+        do_debug(LOG_FATAL, "fseek error:%s", strerror(errno));
+    }
+    while (1) {
+        if (fgetc(fp) == '\n') {
+            ++total_num;
+            len[n - total_num] = 0;
+        } else {
+            ++len[n - total_num];
+        }
+        if (total_num > n) {
+            break;
+        }
+        if (fseek(fp, -2, SEEK_CUR) != 0) {
+            /* goto file head */
+            if (fseek(fp, 0, SEEK_SET) != 0) {
+                do_debug(LOG_FATAL, "fseek error:%s", strerror(errno));
+            }
+            break;
+        }
+    }
+
+    return total_num;
+}
+
+void
+running_check(int check_type)
+{
+    int               total_num, len[2] = {0}, i, j, k;
+    FILE             *fp;
+    char              filename[LEN_128] = {0};
+    char              tmp[10][LEN_4096];
+    char              host_name[LEN_64] = {0};
+    struct            module *mod = NULL;
+    struct            stat statbuf;
+    time_t            nowtime, ts[2] = {0};
+    double           *st_array;
+    char             *line[2];
+    static char       check[LEN_4096 * 11] = {0};
+
+    /* get hostname */
+    if (0 != gethostname(host_name, sizeof(host_name))) {
+        do_debug(LOG_FATAL, "tsar -check: gethostname err, errno=%d", errno);
+    }
+    i = 0;
+    while (host_name[i]) {
+        if (!isprint(host_name[i++])) {
+            host_name[i-1] = '\0';
+            break;
+        }
+    }
+    sprintf(filename, "%s", conf.output_file_path);
+    fp = fopen(filename, "r");
+    if (!fp) {
+        do_debug(LOG_FATAL, "unable to open the log file %s.\n", filename);
+    }
+    /* check file update time */
+    stat(filename, &statbuf);
+    time(&nowtime);
+    if (nowtime - statbuf.st_mtime > 300) {
+        do_debug(LOG_FATAL, "/var/log/tsar.data is far away from now, now time is %d, last time is %d", nowtime, statbuf.st_mtime);
+    }
+    /*FIX ME*/
+    total_num = seek_tail_lines(fp, 2, len);
+    if (total_num == 0) {
+        if (fclose(fp) < 0) {
+            do_debug(LOG_FATAL, "fclose error:%s", strerror(errno));
+        }
+        sprintf(filename, "%s.1", conf.output_file_path);
+        fp = fopen(filename, "r");
+        if (!fp) {
+            do_debug(LOG_FATAL, "unable to open the log file %s.\n", filename);
+        }
+        /* count tsar.data.1 lines */
+        total_num = seek_tail_lines(fp, 2, len);
+        if (total_num < 2) {
+            do_debug(LOG_FATAL, "not enough lines at log file %s.\n", filename);
+        }
+
+        line[0] = malloc(len[0] + 2);
+        if (!fgets(line[0], len[0] + 2, fp)) {
+            do_debug(LOG_FATAL, "fgets error:%s", strerror(errno));
+        }
+        line[1] = malloc(len[1] + 2);
+        if (!fgets(line[1], len[1] + 2, fp)) {
+            do_debug(LOG_FATAL, "fgets error:%s", strerror(errno));
+        }
+
+    } else if (total_num == 1) {
+        line[1] = malloc(len[1] + 2);
+        if (!fgets(line[1], len[1] + 2, fp)) {
+            do_debug(LOG_FATAL, "fgets error:%s", strerror(errno));
+        }
+        if (fclose(fp) < 0) {
+            do_debug(LOG_FATAL, "fclose error:%s", strerror(errno));
+        }
+        sprintf(filename, "%s.1", conf.output_file_path);
+        fp = fopen(filename, "r");
+        if (!fp) {
+            do_debug(LOG_FATAL, "unable to open the log file %s\n", filename);
+        }
+        /* go to the start of the last line at tsar.data.1 */
+        total_num = seek_tail_lines(fp, 1, len);
+
+        if (total_num < 1) {
+            do_debug(LOG_FATAL, "not enough lines at log file %s\n", filename);
+        }
+        line[0] = malloc(len[0] + 2);
+        if (!fgets(line[0], len[0] + 2, fp)) {
+            do_debug(LOG_FATAL, "fgets error:%s", strerror(errno));
+        }
+
+    } else {
+        line[0] = malloc(len[0] + 2);
+        if (!fgets(line[0], len[0] + 2, fp)) {
+            do_debug(LOG_FATAL, "fgets error:%s", strerror(errno));
+        }
+        line[1] = malloc(len[1] + 2);
+        if (!fgets(line[1], len[1] + 2, fp)) {
+            do_debug(LOG_FATAL, "fgets error:%s", strerror(errno));
+        }
+    }
+
+    /*as fp is not used after here,close it */
+    if (fclose(fp) < 0) {
+        do_debug(LOG_FATAL, "fclose error:%s", strerror(errno));
+    }
+    fp = NULL;
+
+    /* set struct module fields */
+    init_module_fields();
+
+    /* read one line to init module parameter */
+    ts[0] = read_line_to_module_record(line[0]);
+    free(line[0]);
+    collect_record_stat();
+
+    ts[1] = read_line_to_module_record(line[1]);
+    free(line[1]);
+    if (ts[0] && ts[1]) {
+        conf.print_interval = ts[1] - ts[0];
+        if (conf.print_interval == 0) {
+            do_debug(LOG_FATAL, "running tsar -c too frequently");
+            return;
+        }
+    }
+    collect_record_stat();
+
+    /*display check detail*/
+    /* ---------------------------RUN_CHECK_NEW--------------------------------------- */
+    if (check_type == RUN_CHECK_NEW) {
+        printf("%s\ttsar\t", host_name);
+        for (i = 0; i < statis.total_mod_num; i++) {
+            mod = mods[i];
+            if (!mod->enable) {
+                continue;
+            }
+            struct mod_info *info = mod->info;
+            /* get mod name */
+            char *mod_name = strstr(mod->opt_line, "--");
+            if (mod_name) {
+                mod_name += 2;
+            }
+
+            char opt[LEN_128] = {0};
+            char *n_record = strdup(mod->record);
+            char *token = strtok(n_record, ITEM_SPLIT);
+            char *s_token;
+
+            for (j = 0; j < mod->n_item; j++) {
+                memset(opt, 0, sizeof(opt));
+                if (token) {
+                    s_token = strpbrk(token, ITEM_SPSTART);
+                    if (s_token) {
+                        strncat(opt, token, s_token - token);
+                        strcat(opt, ":");
+                    }
+                }
+                st_array = &mod->st_array[j * mod->n_col];
+                for (k=0; k < mod->n_col; k++) {
+                    if (mod->spec) {
+                        if (!st_array || !mod->st_flag) {
+                            if (((DATA_SUMMARY == conf.print_mode) && (SPEC_BIT == info[k].summary_bit))
+                                    || ((DATA_DETAIL == conf.print_mode) && (SPEC_BIT == info[k].summary_bit)))
+                            {
+                                printf("%s:%s%s=-%s", mod_name, opt, trim(info[k].hdr, LEN_128), " ");
+                            }
+
+                        } else {
+                            if (((DATA_SUMMARY == conf.print_mode) && (SPEC_BIT == info[k].summary_bit))
+                                    || ((DATA_DETAIL == conf.print_mode) && (SPEC_BIT == info[k].summary_bit)))
+                            {
+                                printf("%s:%s%s=", mod_name, opt, trim(info[k].hdr, LEN_128));
+                                printf("%0.1f ", st_array[k]);
+                            }
+                        }
+
+                    } else {
+                        if (!st_array || !mod->st_flag) {
+                            if (((DATA_SUMMARY == conf.print_mode) && (SUMMARY_BIT == info[k].summary_bit))
+                                    || ((DATA_DETAIL == conf.print_mode) && (HIDE_BIT != info[k].summary_bit)))
+                            {
+                                printf("%s:%s%s=-%s", mod_name, opt, trim(info[k].hdr, LEN_128), " ");
+                            }
+
+                        } else {
+                            if (((DATA_SUMMARY == conf.print_mode) && (SUMMARY_BIT == info[k].summary_bit))
+                                    || ((DATA_DETAIL == conf.print_mode) && (HIDE_BIT != info[k].summary_bit)))
+                            {
+                                printf("%s:%s%s=", mod_name, opt, trim(info[k].hdr, LEN_128));
+                                printf("%0.1f ", st_array[k]);
+                            }
+                        }
+
+                    }
+                }
+                if (token) {
+                    token = strtok(NULL, ITEM_SPLIT);
+                }
+            }
+            if (n_record) {
+                free(n_record);
+                n_record = NULL;
+            }
+        }
+        printf("\n");
+        return;
+    }
 #ifdef OLDTSAR
-/*tsar -check output similar as:
-  v014119.cm3   tsar   apache/qps=5.35 apache/rt=165.89 apache/busy=2 apache/idle=148 cpu=3.58 mem=74.93% load1=0.22 load5=0.27 load15=0.20 xvda=0.15 ifin=131.82 ifout=108.86 TCPretr=0.12 df/=4.04% df/home=10.00% df/opt=71.22% df/tmp=2.07% df/usr=21.27% df/var=5.19% 
- */
-	//------------------------------RUN_CHECK-------------------------------------------
-	if(check_type == RUN_CHECK){
-		for (i = 0; i < statis.total_mod_num; i++) {
-			mod = &mods[i];
-			if (!mod->enable)    
-				continue;
-			if (!strcmp(mod->name,"mod_apache")){
-				for (j = 0; j < mod->n_item; j++) {
-					st_array = &mod->st_array[j * mod->n_col];
-					if(!st_array || !mod->st_flag){
-						sprintf(tmp[0]," apache/qps=- apache/rt=- apache/busy=- apache/idle=-");
-					}else{
-						sprintf(tmp[0]," apache/qps=%0.2f apache/rt=%0.2f apache/busy=%0.0f apache/idle=%0.0f",st_array[0],st_array[1],st_array[3],st_array[4]);
-					}
-				}
-			}
-			if (!strcmp(mod->name,"mod_cpu")){
-				for (j = 0; j < mod->n_item; j++) {
-					st_array = &mod->st_array[j * mod->n_col];
-					if(!st_array || !mod->st_flag){
-						sprintf(tmp[1]," cpu=-");
-					}else{
-						sprintf(tmp[1]," cpu=%0.2f",st_array[5]);
-					}
-				}   
-			}
-			if (!strcmp(mod->name,"mod_mem")){
-				for (j = 0; j < mod->n_item; j++) {
-					st_array = &mod->st_array[j * mod->n_col];
-					if(!st_array || !mod->st_flag){
-						sprintf(tmp[2]," mem=-");
-					}else{
-						sprintf(tmp[2]," mem=%0.2f%%",st_array[5]);
-					}
-				}   
-			}
-			if (!strcmp(mod->name,"mod_load")){
-				for (j = 0; j < mod->n_item; j++) {
-					st_array = &mod->st_array[j * mod->n_col];
-					if(!st_array || !mod->st_flag){
-						sprintf(tmp[3]," load1=- load5=- load15=-");
-					}else{
-						sprintf(tmp[3]," load1=%0.2f load5=%0.2f load15=%0.2f",st_array[0],st_array[1],st_array[2]);
-					}
-				}
-			}
-			if (!strcmp(mod->name,"mod_io")){
-				char opt[LEN_128] = {0};
-				char item[LEN_128] = {0};
-				char *n_record = strdup(mod->record);
-				char *token = strtok(n_record, ITEM_SPLIT);
-				char *s_token;
-				for (j = 0; j < mod->n_item; j++) {
-					s_token = strstr(token, ITEM_SPSTART);
-					if(s_token){
-						memset(opt, 0, sizeof(opt));
-						strncat(opt, token, s_token - token);
-						st_array = &mod->st_array[j * mod->n_col];
-						if(!st_array || !mod->st_flag){
-							sprintf(item," %s=-",opt);
-						}else{
-							sprintf(item," %s=%0.2f",opt,st_array[10]);
-						}
-						strcat(tmp[4],item);
-					}
-					token = strtok(NULL, ITEM_SPLIT);
-				}
-				if(n_record){
-					free(n_record);
-					n_record = NULL;
-				}   
-			}
-			if (!strcmp(mod->name,"mod_traffic")){
-				for (j = 0; j < mod->n_item; j++) {
-					st_array = &mod->st_array[j * mod->n_col];
-					if(!st_array || !mod->st_flag){
-						sprintf(tmp[5]," ifin=- ifout=-");
-					}else{
-						sprintf(tmp[5]," ifin=%0.2f ifout=%0.2f",st_array[0]/1000,st_array[1]/1000);
-					}
-				}   
-			}
-			if (!strcmp(mod->name,"mod_tcp")){
-				for (j = 0; j < mod->n_item; j++) {
-					st_array = &mod->st_array[j * mod->n_col];
-					if(!st_array || !mod->st_flag){
-						sprintf(tmp[6]," TCPretr=-");
-					}else{
-						sprintf(tmp[6]," TCPretr=%0.2f",st_array[4]);
-					}
-				}   
-			}		
-			if (!strcmp(mod->name,"mod_partition")){
-				char opt[LEN_128] = {0};
-				char item[LEN_128] = {0};
-				char *n_record = strdup(mod->record);
-				char *token = strtok(n_record, ITEM_SPLIT);
-				char *s_token;
-				for (j = 0; j < mod->n_item; j++) {
-					s_token = strstr(token, ITEM_SPSTART);
-					if(s_token){
-						memset(opt, 0, sizeof(opt));
-						strncat(opt, token, s_token - token);
-						st_array = &mod->st_array[j * mod->n_col];
-						if(!st_array || !mod->st_flag){
-							sprintf(item," df%s=-",opt);
-						}else{
-							sprintf(item," df%s=%0.2f%%",opt,st_array[3]);
-						}
-						strcat(tmp[7],item);
-					}
-					token = strtok(NULL, ITEM_SPLIT);
-				}
-				if(n_record){
-					free(n_record);
-					n_record = NULL;
-				}   
-			}
-			if (!strcmp(mod->name,"mod_nginx")){
-				for (j = 0; j < mod->n_item; j++) {
-					st_array = &mod->st_array[j * mod->n_col];
-					if(!st_array || !mod->st_flag){
-						sprintf(tmp[8]," nginx/qps=- nginx/rt=-");
-					}else{
-						sprintf(tmp[8]," nginx/qps=%0.2f nginx/rt=%0.2f",st_array[7],st_array[8]);
-					}
-				}
-			}
-		} 
-		for (j = 0; j < 9; j++) {
-			strcat(check,tmp[j]);
-		}  
-		printf("%s\n",check);
-		fclose(fp);
-		fp = NULL;
-	}
+    /*tsar -check output similar as:
+      v014119.cm3   tsar   apache/qps=5.35 apache/rt=165.89 apache/busy=2 apache/idle=148 cpu=3.58 mem=74.93% load1=0.22 load5=0.27 load15=0.20 xvda=0.15 ifin=131.82 ifout=108.86 TCPretr=0.12 df/=4.04% df/home=10.00% df/opt=71.22% df/tmp=2.07% df/usr=21.27% df/var=5.19%
+     */
+    /* ------------------------------RUN_CHECK------------------------------------------- */
+    if (check_type == RUN_CHECK) {
+        //memset(tmp, 0, 10 * LEN_4096);
+        sprintf(check, "%s\ttsar\t", host_name);
+        for (i = 0; i < statis.total_mod_num; i++) {
+            mod = mods[i];
+            if (!mod->enable){
+                continue;
+            }
+            if (!strcmp(mod->name, "mod_apache")) {
+                for (j = 0; j < mod->n_item; j++) {
+                    st_array = &mod->st_array[j * mod->n_col];
+                    if (!st_array || !mod->st_flag) {
+                        sprintf(tmp[0], " apache/qps=- apache/rt=- apache/busy=- apache/idle=-");
+
+                    } else {
+                        sprintf(tmp[0], " apache/qps=%0.2f apache/rt=%0.2f apache/busy=%0.0f apache/idle=%0.0f", st_array[0], st_array[1], st_array[3], st_array[4]);
+                    }
+                }
+            }
+            if (!strcmp(mod->name, "mod_cpu")) {
+                for (j = 0; j < mod->n_item; j++) {
+                    st_array = &mod->st_array[j * mod->n_col];
+                    if (!st_array || !mod->st_flag) {
+                        sprintf(tmp[1], " cpu=-");
+
+                    } else {
+                        sprintf(tmp[1], " cpu=%0.2f", st_array[5]);
+                    }
+                }
+            }
+            if (!strcmp(mod->name, "mod_mem")) {
+                for (j = 0; j < mod->n_item; j++) {
+                    st_array = &mod->st_array[j * mod->n_col];
+                    if (!st_array || !mod->st_flag) {
+                        sprintf(tmp[2], " mem=-");
+
+                    } else {
+                        sprintf(tmp[2], " mem=%0.2f%%", st_array[5]);
+                    }
+                }
+            }
+            if (!strcmp(mod->name, "mod_load")) {
+                for (j = 0; j < mod->n_item; j++) {
+                    st_array = &mod->st_array[j * mod->n_col];
+                    if (!st_array || !mod->st_flag) {
+                        sprintf(tmp[3], " load1=- load5=- load15=-");
+
+                    } else {
+                        sprintf(tmp[3], " load1=%0.2f load5=%0.2f load15=%0.2f", st_array[0], st_array[1], st_array[2]);
+                    }
+                }
+            }
+            if (!strcmp(mod->name, "mod_io")) {
+                char    opt[LEN_128] = {0};
+                char    item[LEN_128] = {0};
+                char   *n_record = strdup(mod->record);
+                char   *token = strtok(n_record, ITEM_SPLIT);
+                char   *s_token;
+                for (j = 0; j < mod->n_item && token != NULL; j++) {
+                    s_token = strpbrk(token, ITEM_SPSTART);
+                    if (s_token) {
+                        memset(opt, 0, sizeof(opt));
+                        strncat(opt, token, s_token - token);
+                        st_array = &mod->st_array[j * mod->n_col];
+                        if (!st_array || !mod->st_flag) {
+                            sprintf(item, " %s=-", opt);
+
+                        } else {
+                            sprintf(item, " %s=%0.2f", opt, st_array[10]);
+                        }
+                        strcat(tmp[4], item);
+                    }
+                    token = strtok(NULL, ITEM_SPLIT);
+                }
+                if (n_record) {
+                    free(n_record);
+                    n_record = NULL;
+                }
+            }
+            if (!strcmp(mod->name, "mod_traffic")) {
+                for (j = 0; j < mod->n_item; j++) {
+                    st_array = &mod->st_array[j * mod->n_col];
+                    if (!st_array || !mod->st_flag) {
+                        sprintf(tmp[5], " ifin=- ifout=-");
+
+                    } else {
+                        sprintf(tmp[5], " ifin=%0.2f ifout=%0.2f", st_array[0] / 1000, st_array[1] / 1000);
+                    }
+                }
+            }
+            if (!strcmp(mod->name, "mod_tcp")) {
+                for (j = 0; j < mod->n_item; j++) {
+                    st_array = &mod->st_array[j * mod->n_col];
+                    if (!st_array || !mod->st_flag) {
+                        sprintf(tmp[6], " TCPretr=-");
+
+                    } else {
+                        sprintf(tmp[6], " TCPretr=%0.2f", st_array[7]);
+                    }
+                }
+            }
+            if (!strcmp(mod->name, "mod_partition")) {
+                char    opt[LEN_128] = {0};
+                char    item[LEN_128] = {0};
+                char   *n_record = strdup(mod->record);
+                char   *token = strtok(n_record, ITEM_SPLIT);
+                char   *s_token;
+                for (j = 0; j < mod->n_item && token != NULL; j++) {
+                    s_token = strpbrk(token, ITEM_SPSTART);
+                    if (s_token) {
+                        memset(opt, 0, sizeof(opt));
+                        strncat(opt, token, s_token - token);
+                        st_array = &mod->st_array[j * mod->n_col];
+                        if (!st_array || !mod->st_flag) {
+                            sprintf(item, " df%s=-", opt);
+
+                        } else {
+                            sprintf(item, " df%s=%0.2f%%", opt, st_array[3]);
+                        }
+                        strcat(tmp[7], item);
+                    }
+                    token = strtok(NULL, ITEM_SPLIT);
+                }
+                if (n_record) {
+                    free(n_record);
+                    n_record = NULL;
+                }
+            }
+            if (!strcmp(mod->name, "mod_nginx")){
+                for (j = 0; j < mod->n_item; j++) {
+                    st_array = &mod->st_array[j * mod->n_col];
+                    if (!st_array || !mod->st_flag) {
+                        sprintf(tmp[8], " nginx/qps=- nginx/rt=-");
+
+                    } else {
+                        sprintf(tmp[8], " nginx/qps=%0.2f nginx/rt=%0.2f", st_array[7], st_array[8]);
+                    }
+                }
+            }
+            if (!strcmp(mod->name, "mod_swap")) {
+                for (j = 0; j < mod->n_item; j++) {
+                    st_array = &mod->st_array[j * mod->n_col];
+                    if (!st_array || !mod->st_flag) {
+                        sprintf(tmp[9], " swap/total=- swap/util=-");
+
+                    } else {
+                        sprintf(tmp[9], " swap/total=%0.2f swap/util=%0.2f%%", st_array[2] / 1024 / 1024, st_array[3]);
+                    }
+                }
+            }
+        }
+        for (j = 0; j < 10; j++) {
+            strcat(check, tmp[j]);
+        }
+        printf("%s\n", check);
+    }
 #endif
 }
 /*end*/
diff --git a/src/output_tcp.c b/src/output_tcp.c
new file mode 100644
index 0000000..f04bd0c
--- /dev/null
+++ b/src/output_tcp.c
@@ -0,0 +1,117 @@
+
+/*
+ * (C) 2010-2011 Alibaba Group Holding Limited
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+
+#include <fcntl.h>
+#include "tsar.h"
+
+void
+send_data_tcp(char *output_addr, char *data, int len)
+{
+    int        fd, flags, res;
+    fd_set     fdr, fdw;
+    struct     timeval timeout;
+    struct     sockaddr_in db_addr;
+
+    fd = socket(AF_INET, SOCK_STREAM, 0);
+    if (fd < 0) {
+        do_debug(LOG_FATAL, "can't get socket");
+    }
+
+    /* set socket fd noblock */
+    if ((flags = fcntl(fd, F_GETFL, 0)) < 0) {
+        close(fd);
+        return;
+    }
+
+    if (fcntl(fd, F_SETFL, flags | O_NONBLOCK) < 0) {
+        close(fd);
+        return;
+    }
+
+    /* get db server address */
+    db_addr = *str2sa(output_addr);
+
+    if (connect(fd, (struct sockaddr*)&db_addr, sizeof(db_addr)) != 0) {
+        if (errno != EINPROGRESS) { // EINPROGRESS
+            close(fd);
+            return;
+
+        } else {
+            goto select;
+        }
+
+    } else {
+        goto send;
+    }
+
+select:
+    FD_ZERO(&fdr);
+    FD_ZERO(&fdw);
+    FD_SET(fd, &fdr);
+    FD_SET(fd, &fdw);
+
+    timeout.tv_sec = 2;
+    timeout.tv_usec = 0;
+
+    res = select(fd + 1, &fdr, &fdw, NULL, &timeout);
+    if (res <= 0) {
+        close(fd);
+        return;
+    }
+
+send:
+    if (len > 0 && write(fd, data, len) != len) {
+        do_debug(LOG_ERR, "output_db write error:dst:%s\terrno:%s\n",output_addr, strerror(errno));
+    }
+    close(fd);
+}
+
+void
+output_multi_tcp(int have_collect)
+{
+    int           out_pipe[2];
+    int           len;
+    static char   data[LEN_10M] = {0};
+    int         i;
+    /* only output from output_tcp_mod */
+    reload_modules(conf.output_tcp_mod);
+
+    if (!strcasecmp(conf.output_tcp_merge, "on") || !strcasecmp(conf.output_tcp_merge, "enable")) {
+        conf.print_merge = MERGE_ITEM;
+    } else {
+        conf.print_merge = MERGE_NOT;
+    }
+
+    if (pipe(out_pipe) != 0) {
+        return;
+    }
+
+    dup2(out_pipe[1], STDOUT_FILENO);
+    close(out_pipe[1]);
+
+    running_check(RUN_CHECK_NEW);
+
+    fflush(stdout);
+    len = read(out_pipe[0], data, LEN_10M);
+    close(out_pipe[0]);
+    /*now ,the data to send is gotten*/
+    for(i = 0; i < conf.output_tcp_addr_num; i++){
+        send_data_tcp(conf.output_tcp_addr[i], data, len);
+    }
+}
diff --git a/src/tsar.c b/src/tsar.c
index 401d058..7c84ff2 100644
--- a/src/tsar.c
+++ b/src/tsar.c
@@ -1,3 +1,4 @@
+
 /*
  * (C) 2010-2011 Alibaba Group Holding Limited
  *
@@ -15,283 +16,334 @@
  *
  */
 
+
 #include "tsar.h"
 
+
 struct statistic statis;
 struct configure conf;
-struct module	mods[MAX_MOD_NUM];
+struct module   *mods[MAX_MOD_NUM];
+lua_State *L = NULL;
+
 
-void usage()
+void
+usage()
 {
-	int i;
-	struct module *mod;
+    int    i;
+    struct module *mod;
 
-	fprintf(stderr,
-			"Usage: tsar [options]\n"
-			"Options:\n"
+    fprintf(stderr,
+            "Usage: tsar [options]\n"
+            "Options:\n"
 #ifdef OLDTSAR
-			/*used for check alert*/
-			"    -check		display last record for alert\n"
-			//"    -current		display last record for alert\n"
-			/*end*/
+            /*used for check alert*/
+            "    -check         display last record for alert\n"
+            /*end*/
 #endif
-			"    --check/-C		display last record for alert.example:tsar --check / tsar --check --cpu --io\n"
-			"    --cron/-c		run in cron mode, output data to file\n"
-			"    --interval/-i	specify intervals numbers, in minutes if with --live, it is in seconds\n"
-			"    --list/-L		list enabled modules\n"
-			"    --live/-l		running print live mode, which module will print\n"
-			"    --file/-f		specify a filepath as input\n"
-			"    --ndays/-n		show the value for the past days (default: 1)\n"
-			"    --date/-d		show the value for the specify day(n or YYYYMMDD)\n"
-			"    --merge/-m		merge multiply item to one\n"
-			"    --detail/-D	\tdo not conver data to K/M/G\n"
-			"    --spec/-s		show spec field data, tsar --cpu -s sys,util\n"
-			"    --help/-h		help\n");
-
-	fprintf(stderr,
-			"Modules Enabled:\n"
-	       );
-
-	for (i = 0; i < statis.total_mod_num; i++) {
-		mod = &mods[i];
-		if(mod->usage) {
-			fprintf(stderr, "%s", mod->usage);
-			fprintf(stderr, "\n");
-		}
-	}
-
-	exit(0);
+            "    --check/-C     display last record for alert.example:tsar --check / tsar --check --cpu --io\n"
+            "    --watch/-w     display last records in N mimutes. example:tsar --watch 30 / tsar --watch 30 --cpu --io\n"
+            "    --cron/-c      run in cron mode, output data to file\n"
+            "    --interval/-i  specify intervals numbers, in minutes if with --live, it is in seconds\n"
+            "    --list/-L      list enabled modules\n"
+            "    --live/-l      running print live mode, which module will print\n"
+            "    --file/-f      specify a filepath as input\n"
+            "    --ndays/-n     show the value for the past days (default: 1)\n"
+            "    --date/-d      show the value for the specify day(n or YYYYMMDD)\n"
+            "    --merge/-m     merge multiply item to one\n"
+            "    --detail/-D    do not conver data to K/M/G\n"
+            "    --spec/-s      show spec field data, tsar --cpu -s sys,util\n"
+            "    --item/-I      show spec item data, tsar --io -I sda\n"
+            "    --help/-h      help\n");
+
+    fprintf(stderr,
+            "Modules Enabled:\n"
+           );
+
+    for (i = 0; i < statis.total_mod_num; i++) {
+        mod = mods[i];
+        fprintf(stderr, "%s\n", mod->usage);
+    }
+
+    exit(0);
 }
 
 
 struct option longopts[] = {
-	{ "cron", no_argument, NULL, 'c' },
-	{ "check", no_argument, NULL, 'C' },
-	{ "interval", required_argument, NULL, 'i' },
-	{ "list", no_argument, NULL, 'L' },
-	{ "live", no_argument, NULL, 'l' },
-	{ "file", required_argument, NULL, 'f' },
-	{ "ndays", required_argument, NULL, 'n' },
-	{ "date", required_argument, NULL, 'd' },
-	{ "merge", no_argument, NULL, 'm' },
-	{ "detail", no_argument, NULL, 'D' },
-	{ "spec", required_argument, NULL, 's' },
-	{ "help", no_argument, NULL, 'h' },
-	{ 0, 0, 0, 0},
+    { "cron", no_argument, NULL, 'c' },
+    { "check", no_argument, NULL, 'C' },
+    { "watch", required_argument, NULL, 'w' },
+    { "interval", required_argument, NULL, 'i' },
+    { "list", no_argument, NULL, 'L' },
+    { "live", no_argument, NULL, 'l' },
+    { "file", required_argument, NULL, 'f' },
+    { "ndays", required_argument, NULL, 'n' },
+    { "date", required_argument, NULL, 'd' },
+    { "merge", no_argument, NULL, 'm' },
+    { "detail", no_argument, NULL, 'D' },
+    { "spec", required_argument, NULL, 's' },
+    { "item", required_argument, NULL, 'I' },
+    { "help", no_argument, NULL, 'h' },
+    { 0, 0, 0, 0},
 };
 
 
-static void main_init(int argc, char **argv)
+static void
+main_init(int argc, char **argv)
 {
-	int opt, oind = 0;
+    int    opt, oind = 0;
 #ifdef OLDTSAR
-	/* check option for tsar1.0 */
-	if(argc >= 2){
-		if(!strcmp(argv[1],"-check") && argc == 2){
-			conf.running_mode = RUN_CHECK;
-			conf.print_mode = DATA_DETAIL;
-			conf.print_interval = 60;
-			conf.print_tail = 0;
-			conf.print_nline_interval = conf.print_interval;
-			return;
-		}
-	}
-	/*end*/
+    /* check option for tsar1.0 */
+    if (argc >= 2) {
+        if (!strcmp(argv[1], "-check") && argc == 2) {
+            conf.running_mode = RUN_CHECK;
+            conf.print_mode = DATA_DETAIL;
+            conf.print_interval = 60;
+            conf.print_tail = 0;
+            conf.print_nline_interval = conf.print_interval;
+            return;
+        }
+    }
+    /*end*/
 #endif
-	while ((opt = getopt_long(argc, argv, ":cCi:Llf:n:d:s:mhD", longopts, NULL)) != -1) {
-		oind++;
-		switch (opt) {
-			case 'c':
-				conf.running_mode = RUN_CRON;
-				break;
-			case 'C':
-				conf.running_mode = RUN_CHECK_NEW;
-				break;
-			case 'i':
-				conf.print_interval = atoi(optarg);
-				oind++;
-				break;
-			case 'L':
-				conf.running_mode = RUN_LIST;
-				break;
-			case 'l':
-				conf.running_mode = RUN_PRINT_LIVE;
-				break;
-			case 'f':
-				strcpy(conf.output_file_path ,optarg);
-				break;
-			case 's':
-				set_special_field(optarg);
-				break;
-			case 'n':
-				conf.print_ndays = atoi(optarg);
-				oind++;
-				break;
-			case 'd':
-				conf.print_day = atoi(optarg);
-				oind++;
-				break;
-			case 'm':
-				conf.print_merge  = MERGE_ITEM;
-				break;
-			case 'D':
-				conf.print_detail = TRUE;
-				break;
-			case 'h':
-				usage();
-			case ':':
-				printf("must have parameter\n");
-				usage();
-			case '?':
-				if (argv[oind] && strstr(argv[oind], "--")) {
-					strcat(conf.output_print_mod, argv[oind]);
-					strcat(conf.output_print_mod, DATA_SPLIT);
-				} else
-					usage();
-		}
-	}
-	/* set default parameter */
-	if (!conf.print_ndays)
-		conf.print_ndays = 1;
-
-	if (!conf.print_interval)
-		conf.print_interval = DEFAULT_PRINT_INTERVAL;
-
-	if (RUN_NULL == conf.running_mode)
-		conf.running_mode = RUN_PRINT;
-
-	if(conf.running_mode == RUN_CHECK_NEW){
-		conf.print_interval = 60;
-		conf.print_tail = 0;
-		conf.print_nline_interval = conf.print_interval;
-	}
-
-	if (!strlen(conf.output_print_mod))
-		conf.print_mode = DATA_SUMMARY;
-	else
-		conf.print_mode = DATA_DETAIL;
-
-	strcpy(conf.config_file, DEFAULT_CONF_FILE_PATH);
-	if (access(conf.config_file, F_OK)) {
-		do_debug(LOG_FATAL, "main_init: can't find tsar.conf");
-	}
+    while ((opt = getopt_long(argc, argv, ":cCw:i:Llf:n:d:s:I:mhD", longopts, NULL)) != -1) {
+        oind++;
+        switch (opt) {
+            case 'c':
+                conf.running_mode = RUN_CRON;
+                break;
+            case 'C':
+                conf.running_mode = RUN_CHECK_NEW;
+                break;
+            case 'w':
+                conf.running_mode = RUN_WATCH;
+                conf.print_nminute = atoi(optarg);
+                oind++;
+                break;
+            case 'i':
+                conf.print_interval = atoi(optarg);
+                oind++;
+                break;
+            case 'L':
+                conf.running_mode = RUN_LIST;
+                break;
+            case 'l':
+                conf.running_mode = RUN_PRINT_LIVE;
+                break;
+            case 'f':
+                strncpy(conf.output_file_path, optarg, LEN_128);
+                break;
+            case 's':
+                set_special_field(optarg);
+                break;
+            case 'I':
+                set_special_item(optarg);
+                break;
+            case 'n':
+                conf.print_ndays = atoi(optarg);
+                oind++;
+                break;
+            case 'd':
+                conf.print_day = atoi(optarg);
+                oind++;
+                break;
+            case 'm':
+                conf.print_merge  = MERGE_ITEM;
+                break;
+            case 'D':
+                conf.print_detail = TRUE;
+                break;
+            case 'h':
+                usage();
+                break;
+            case ':':
+                printf("must have parameter\n");
+                usage();
+                break;
+            case '?':
+                if (argv[oind] && strstr(argv[oind], "--")) {
+                    strncat(conf.output_print_mod, argv[oind], LEN_512 - sizeof(DATA_SPLIT));
+                    strcat(conf.output_print_mod, DATA_SPLIT);
+
+                } else {
+                    usage();
+                }
+        }
+    }
+    /* set default parameter */
+    if (!conf.print_ndays) {
+        conf.print_ndays = 1;
+    }
+
+    if (!conf.print_interval) {
+        conf.print_interval = DEFAULT_PRINT_INTERVAL;
+    }
+
+    if (RUN_NULL == conf.running_mode) {
+        conf.running_mode = RUN_PRINT;
+
+    } else if (conf.running_mode == RUN_CHECK_NEW) {
+        conf.print_interval = 60;
+        conf.print_tail = 0;
+    }
+
+    if (!strlen(conf.output_print_mod)) {
+        conf.print_mode = DATA_SUMMARY;
+
+    } else {
+        conf.print_mode = DATA_DETAIL;
+    }
+
+    strcpy(conf.config_file, DEFAULT_CONF_FILE_PATH);
+    if (access(conf.config_file, F_OK)) {
+        do_debug(LOG_FATAL, "main_init: can't find tsar.conf");
+    }
 }
 
 
-void shut_down()
+void
+shut_down()
 {
-	free_modules();
+    close_luavm(L);
+    free_modules();
 
-	memset(&conf, 0, sizeof(struct configure));
-	memset(&mods, 0, sizeof(struct module) * MAX_MOD_NUM);
-	memset(&statis, 0, sizeof(struct statistic));
+/*
+    memset(&conf, 0, sizeof(struct configure));
+    memset(mods, 0, sizeof(mods));
+    memset(&statis, 0, sizeof(struct statistic));
+*/
 }
 
 
-void running_list()
+void
+running_list()
 {
-	int i;
-	struct module *mod;
+    int    i;
+    struct module *mod;
 
-	printf("tsar enable follow modules:\n");
+    printf("tsar enable follow modules:\n");
 
-	for (i = 0; i < statis.total_mod_num; i++) {
-		mod = &mods[i];
-		printf("	%s\n", mod->name + 4);
-	}
+    for (i = 0; i < statis.total_mod_num; i++) {
+        mod = mods[i];
+        printf("    %s\n", mod->name + 4);
+    }
 }
 
 
-void running_cron()
+void
+running_cron()
 {
-	int have_collect = 0;
-	/* output interface */
-	if (strstr(conf.output_interface, "file")) {
-		/* output data */
-		collect_record();
-		output_file();
-		have_collect = 1;
-	}
-
-	if (strstr(conf.output_interface, "db")) {
-		output_db(have_collect);
-	}
-	if (strstr(conf.output_interface, "nagios")) {
-		output_nagios();
-	}
+    int    have_collect = 0;
+    /* output interface */
+    if (strstr(conf.output_interface, "file")) {
+        /* output data */
+        collect_record();
+        output_file();
+        have_collect = 1;
+    }
+
+    if (strstr(conf.output_interface, "db")) {
+        output_db(have_collect);
+    }
+    if (strstr(conf.output_interface, "nagios")) {
+        output_nagios();
+    }
+    if (strstr(conf.output_interface, "tcp")) {
+        output_multi_tcp(have_collect);
+    }
 }
 
 
-int main(int argc, char **argv)
+int
+main(int argc, char **argv)
 {
-	parse_config_file(DEFAULT_CONF_FILE_PATH);
 
-	load_modules();
+    parse_config_file(DEFAULT_CONF_FILE_PATH);
+
+    L = load_luavm();
+    if (L == NULL) {
+        do_debug(LOG_ERR, "load lua vm err");
+        return 1;
+    }
+
+    load_modules();
 
-	statis.cur_time = time(NULL);
+    statis.cur_time = time(NULL);
 
-	conf.print_day = -1;
+    conf.print_day = -1;
 
-	main_init(argc, argv);
+    main_init(argc, argv);
 
-	/*
-	 * enter running
-	 */
-	switch (conf.running_mode) {
-		case RUN_LIST:
-			running_list();
-			break;
+    /*
+     * enter running
+     */
+    switch (conf.running_mode) {
+        case RUN_LIST:
+            running_list();
+            break;
 
-		case RUN_CRON:
-			conf.print_mode = DATA_DETAIL;
-			running_cron();
-			break;
+        case RUN_CRON:
+            conf.print_mode = DATA_DETAIL;
+            running_cron();
+            break;
 #ifdef OLDTSAR
-			/*for check option*/
-		case RUN_CHECK:
-			reload_check_modules();
-			/* disable module when n_col is zero */
-			running_check(RUN_CHECK);
-			break;
-			/*end*/
+            /*for check option*/
+        case RUN_CHECK:
+            reload_check_modules();
+            /* disable module when n_col is zero */
+            running_check(RUN_CHECK);
+            break;
+            /*end*/
 #endif
-		case RUN_CHECK_NEW:
-			if(reload_modules(conf.output_print_mod)){
-				conf.print_mode = DATA_DETAIL;
-			};
-			/* disable module when n_col is zero */
-			disable_col_zero();
-			running_check(RUN_CHECK_NEW);
-			break;
-		case RUN_PRINT:
-			/* reload module by output_stdio_mod and output_print_mod*/
-			reload_modules(conf.output_stdio_mod);
-			reload_modules(conf.output_print_mod);
-
-			/* disable module when n_col is zero */
-			disable_col_zero();
-
-			/* set conf.print_nline_interval */
-			conf.print_nline_interval = conf.print_interval;
-
-			running_print();
-			break;
-
-		case RUN_PRINT_LIVE:
-			/* reload module by output_stdio_mod and output_print_mod*/
-			reload_modules(conf.output_stdio_mod);
-			reload_modules(conf.output_print_mod);
-
-			/* disable module when n_col is zero */
-			disable_col_zero();
-
-			running_print_live();
-			break;
-
-		default:
-			break;
-	}
-
-	shut_down();
-	return 0;
+        case RUN_CHECK_NEW:
+            if (reload_modules(conf.output_print_mod)) {
+                conf.print_mode = DATA_DETAIL;
+            };
+            /* disable module when n_col is zero */
+            disable_col_zero();
+            running_check(RUN_CHECK_NEW);
+            break;
+        case RUN_PRINT:
+            /* reload module by output_stdio_mod and output_print_mod*/
+            reload_modules(conf.output_stdio_mod);
+            reload_modules(conf.output_print_mod);
+
+            /* disable module when n_col is zero */
+            disable_col_zero();
+
+            /* set conf.print_nline_interval */
+            conf.print_nline_interval = conf.print_interval;
+
+            running_print();
+            break;
+
+        case RUN_PRINT_LIVE:
+            /* reload module by output_stdio_mod and output_print_mod*/
+            reload_modules(conf.output_stdio_mod);
+            reload_modules(conf.output_print_mod);
+
+            /* disable module when n_col is zero */
+            disable_col_zero();
+
+            running_print_live();
+            break;
+        case RUN_WATCH:
+            /* reload module by output_stdio_mod and output_print_mod*/
+            reload_modules(conf.output_stdio_mod);
+            reload_modules(conf.output_print_mod);
+
+            /* disable module when n_col is zero */
+            disable_col_zero();
+
+            /* set conf.print_nline_interval */
+            conf.print_nline_interval = conf.print_interval;
+
+            running_print();
+            break;
+
+        default:
+            break;
+    }
+
+    shut_down();
+    return 0;
 }
diff --git a/src/tsar_lua_util.c b/src/tsar_lua_util.c
new file mode 100644
index 0000000..a9fb31c
--- /dev/null
+++ b/src/tsar_lua_util.c
@@ -0,0 +1,449 @@
+
+/*
+ * (C) 2010-2011 Alibaba Group Holding Limited
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+
+#include "tsar.h"
+
+
+static void
+lua_set_mod(lua_State *L, struct module *mod)
+{
+    lua_newtable(L);
+    lua_pushstring(L, "usage");
+    lua_pushstring(L, mod->usage);
+    lua_settable(L, -3);
+
+    lua_pushstring(L, "opt");
+    lua_pushstring(L, mod->opt_line);
+    lua_settable(L, -3);
+
+    lua_pushstring(L, "n_col");
+    lua_pushinteger(L, mod->n_col);
+    lua_settable(L, -3);
+}
+
+
+static void
+inject_lua_package_path(lua_State *L)
+{
+    const char *old_path;
+    char new_path[LEN_512];
+
+    if (strlen(conf.lua_path)) {
+        lua_getglobal(L, "package");
+        /* get original package.path */
+        lua_getfield(L, -1, "path");
+        old_path = lua_tostring(L, -1);
+        do_debug(LOG_DEBUG, "old lua package path: %s\n", old_path);
+        lua_pop(L, 1);
+
+        sprintf(new_path, "%s;%s", conf.lua_path, old_path);
+        do_debug(LOG_DEBUG, "new lua package path: %s\n", new_path);
+        lua_pushstring(L, new_path);
+        lua_setfield(L, -2, "path");
+    }
+
+    if (strlen(conf.lua_cpath)) {
+        lua_getglobal(L, "package");
+        /* get original package.path */
+        lua_getfield(L, -1, "cpath");
+        old_path = lua_tostring(L, -1);
+        do_debug(LOG_DEBUG, "old lua package cpath: %s\n", old_path);
+        lua_pop(L, 1);
+
+        sprintf(new_path, "%s;%s", conf.lua_cpath, old_path);
+        do_debug(LOG_DEBUG, "new lua package cpath: %s\n", new_path);
+        lua_pushstring(L, new_path);
+        lua_setfield(L, -2, "cpath");
+    }
+
+    lua_pop(L, 2);
+}
+
+
+static void
+inject_tsar_consts(lua_State *L)
+{
+    lua_pushinteger(L, HIDE_BIT);
+    lua_setfield(L, -2, "HIDE_BIT");
+
+    lua_pushinteger(L, DETAIL_BIT);
+    lua_setfield(L, -2, "DETAIL_BIT");
+
+    lua_pushinteger(L, SUMMARY_BIT);
+    lua_setfield(L, -2, "SUMMARY_BIT");
+
+    lua_pushinteger(L, SPEC_BIT);
+    lua_setfield(L, -2, "SPEC_BIT");
+
+    lua_pushinteger(L, MERGE_NULL);
+    lua_setfield(L, -2, "MERGE_NULL");
+
+    lua_pushinteger(L, MERGE_SUM);
+    lua_setfield(L, -2, "MERGE_SUM");
+
+    lua_pushinteger(L, MERGE_AVG);
+    lua_setfield(L, -2, "MERGE_AVG");
+
+    lua_pushinteger(L, STATS_NULL);
+    lua_setfield(L, -2, "STATS_NULL");
+
+    lua_pushinteger(L, STATS_SUB);
+    lua_setfield(L, -2, "STATS_SUB");
+
+    lua_pushinteger(L, STATS_SUB_INTER);
+    lua_setfield(L, -2, "STATS_SUB_INTER");
+}
+
+
+static void
+inject_tsar_api(lua_State *L)
+{
+    /* tsar */
+    lua_newtable(L);
+
+    inject_tsar_consts(L);
+
+    lua_setglobal(L, "tsar");
+}
+
+
+static int
+load_lua_module_info(lua_State *L, struct module *mod)
+{
+    int i = 0;
+    int info_len = 0;
+
+
+    lua_getfield(L, -1, "info");
+    if (!lua_istable(L, -1)) {
+        do_debug(LOG_ERR, "load_lua_module info isn't table\n");
+        return 1;
+    }
+
+    info_len = lua_objlen(L, -1);
+    if (info_len == 0) {
+        return 0;
+    }
+    mod->n_col = info_len;
+
+    if (mod->info) {
+        do_debug(LOG_ERR, "load_lua_module duplicated malloc info\n");
+        return 1;
+    }
+
+    mod->info = malloc(info_len * sizeof(struct mod_info));
+    if (!mod->info) {
+        do_debug(LOG_ERR, "load_lua_module malloc info error\n");
+        return 1;
+    }
+
+    for (i = 0; i < info_len; i ++) {
+        lua_rawgeti(L, -1, i + 1); // lua begin from 1
+        if (!lua_istable(L, -1)) {
+            do_debug(LOG_ERR, "load_lua_module info[%d] isn't table\n", i);
+            return 1;
+        }
+        lua_getfield(L, -1, "hdr");
+        if (!lua_isstring(L, -1)) {
+            do_debug(LOG_ERR, "load_lua_module info.hdr isn't string\n");
+            return 1;
+        }
+        sprintf(mod->info[i].hdr, "%s", lua_tostring(L, -1));
+        lua_pop(L, 1);
+
+        lua_getfield(L, -1, "summary_bit");
+        if (!lua_isnumber(L, -1)) {
+            do_debug(LOG_ERR, "load_lua_module info.summary_bit isn't number\n");
+            return 1;
+        }
+        mod->info[i].summary_bit = lua_tointeger(L, -1);
+        lua_pop(L, 1);
+
+        lua_getfield(L, -1, "merge_mode");
+        if (!lua_isnumber(L, -1)) {
+            do_debug(LOG_ERR, "load_lua_module info.merge_mode isn't number\n");
+            return 1;
+        }
+        mod->info[i].merge_mode = lua_tointeger(L, -1);
+        lua_pop(L, 1);
+
+        lua_getfield(L, -1, "stats_opt");
+        if (!lua_isnumber(L, -1)) {
+            do_debug(LOG_ERR, "load_lua_module info.stats_opt isn't number\n");
+            return 1;
+        }
+        mod->info[i].stats_opt = lua_tointeger(L, -1);
+        lua_pop(L, 1);
+
+        lua_pop(L, 1);
+        do_debug(LOG_DEBUG, "load_lua_module hdr:%s summary_bit:%d, merge_mode:%d, stats_opt:%d\n",
+            mod->info[i].hdr, mod->info[i].summary_bit, mod->info[i].merge_mode, mod->info[i].stats_opt);
+    }
+
+    lua_pop(L, 2);
+
+    return 0;
+}
+
+
+static int
+load_lua_module_optusage(lua_State *L, struct module *mod)
+{
+    lua_getfield(L, -1, "opt");
+    if (!lua_isstring(L, -1)) {
+        do_debug(LOG_ERR, "load_lua_module opt isn't string\n");
+        return 1;
+    }
+    sprintf(mod->opt_line, "%s", lua_tostring(L, -1));
+    do_debug(LOG_DEBUG, "load_lua_module opt:%s\n", mod->opt_line);
+    lua_pop(L, 1);
+
+    lua_getfield(L, -1, "usage");
+    if (!lua_isstring(L, -1)) {
+        do_debug(LOG_ERR, "load_lua_module usage isn't string\n");
+        return 1;
+    }
+    sprintf(mod->usage, "    %-20s%s", mod->opt_line, lua_tostring(L, -1));
+    do_debug(LOG_DEBUG, "load_lua_module usage:%s\n", mod->usage);
+    lua_pop(L, 1);
+
+    return 0;
+}
+
+
+static int
+load_lua_module_register(lua_State *L, struct module *mod)
+{
+    lua_getfield(L, -1, "register");
+    if (lua_pcall(L, 0, 1, 0) != 0) {
+        do_debug(LOG_ERR, "load_lua_module call _M.register() err %s\n", lua_tostring(L, -1));
+        return 1;
+    }
+
+    if (load_lua_module_optusage(L, mod) != 0) {
+        return 1;
+    }
+
+    if (load_lua_module_info(L, mod) != 0) {
+        return 1;
+    }
+
+    return 0;
+}
+
+
+void
+close_luavm(lua_State *L)
+{
+    lua_close(L);
+}
+
+
+lua_State *
+load_luavm()
+{
+    lua_State *vm;
+
+    vm = luaL_newstate();
+    if (vm == NULL) {
+        return NULL;
+    }
+
+    luaL_openlibs(vm);
+
+    inject_lua_package_path(vm);
+    inject_tsar_api(vm);
+
+    return vm;
+}
+
+
+static void
+lua_module_set_st_record_wrapper(struct module *mod, double st_array[],
+    U_64 pre_array[], U_64 cur_array[], int inter)
+{
+    int        i;
+
+    lua_getglobal(L, mod->name);
+    if (!lua_istable(L, -1)) {
+        do_debug(LOG_ERR, "lua_module_set_st_record_wrapper %s isn's table\n", mod->name);
+        return;
+    }
+
+    lua_getfield(L, -1, "set");
+    if (lua_isnil(L, -1)) {
+        do_debug(LOG_DEBUG, "lua_module_set_st_record_wrapper %s.set() doesnt set\n", mod->name);
+        for (i = 0; i < mod->n_col; i++) {
+            st_array[i] = cur_array[i] - pre_array[i];
+        }
+        return;
+    } else if (!lua_isfunction(L, -1)) {
+        do_debug(LOG_ERR, "lua_module_set_st_record_wrapper %s.set() isnt function\n", mod->name);
+        return;
+    }
+
+    lua_set_mod(L, mod);
+
+    lua_newtable(L);
+    for (i = 0; i < mod->n_col; i++) {
+        lua_pushnumber(L, st_array[i]);
+        lua_rawseti(L, -2, i+1);
+    }
+
+    lua_newtable(L);
+    for (i = 0; i < mod->n_col; i++) {
+        lua_pushnumber(L, pre_array[i]);
+        lua_rawseti(L, -2, i+1);
+    }
+
+    lua_newtable(L);
+    for (i = 0; i < mod->n_col; i++) {
+        lua_pushnumber(L, cur_array[i]);
+        lua_rawseti(L, -2, i+1);
+    }
+
+    lua_pushnumber(L, inter);
+
+    if (lua_pcall(L, 5, 3, 0) != 0) {
+        do_debug(LOG_ERR, "lua_module_set_st_record_wrapper call set() err %s\n", lua_tostring(L, -1));
+        return;
+    }
+
+    if (!lua_istable(L, -1)) {
+        do_debug(LOG_ERR, "lua_module_set_st_record_wrapper set() return 3rd nontable\n");
+        return;
+    }
+
+    if (!lua_istable(L, -2)) {
+        do_debug(LOG_ERR, "lua_module_set_st_record_wrapper set() return 2nd nontable\n");
+        return;
+    }
+
+    if (!lua_istable(L, -3)) {
+        do_debug(LOG_ERR, "lua_module_set_st_record_wrapper set() return 1st nontable\n");
+        return;
+    }
+
+    for (i = 0; i < mod->n_col; i++) {
+        lua_rawgeti(L, -1, i + 1);
+        if (!lua_isnumber(L, -1)) {
+            continue;
+        }
+        cur_array[i] = lua_tonumber(L, -1);
+        lua_pop(L, 1);
+    }
+
+    lua_pop(L, 1);
+    for (i = 0; i < mod->n_col; i++) {
+        lua_rawgeti(L, -1, i + 1);
+        if (!lua_isnumber(L, -1)) {
+            continue;
+        }
+        pre_array[i] = lua_tonumber(L, -1);
+        lua_pop(L, 1);
+    }
+
+    lua_pop(L, 1);
+    for (i = 0; i < mod->n_col; i++) {
+        lua_rawgeti(L, -1, i + 1);
+        if (!lua_isnumber(L, -1)) {
+            continue;
+        }
+        st_array[i] = lua_tonumber(L, -1);
+        lua_pop(L, 1);
+    }
+
+    lua_pop(L, lua_gettop(L));
+}
+
+
+static void
+lua_module_data_collect_wrapper(struct module *mod, char *parameter)
+{
+    lua_getglobal(L, mod->name);
+    if (!lua_istable(L, -1)) {
+        do_debug(LOG_ERR, "lua_module_data_collect_wrapper %s isn's table\n", mod->name);
+        return;
+    }
+
+    lua_getfield(L, -1, "read");
+    if (lua_isnil(L, -1)) {
+        do_debug(LOG_DEBUG, "lua_module_data_collect_wrapper %s.read() doesnt set\n", mod->name);
+        return;
+    } else if (lua_isfunction(L, -1) == 0) {
+        do_debug(LOG_ERR, "lua_module_data_collect_wrapper %s.read() isnt function\n", mod->name);
+        return;
+    }
+
+    lua_set_mod(L, mod);
+    lua_pushstring(L, parameter);
+
+    if (lua_pcall(L, 2, 1, 0) != 0) {
+        do_debug(LOG_ERR, "lua_module_data_collect_wrapper call %s.read() err %s\n", mod->name, lua_tostring(L, -1));
+        return;
+    }
+
+    if (!lua_isstring(L, -1)) {
+        do_debug(LOG_ERR, "lua_module_data_collect_wrapper %s.read() function return value isnt string\n", mod->name);
+        return;
+    }
+
+    set_mod_record(mod, lua_tostring(L, -1));
+}
+
+
+void
+load_lua_module(lua_State *L, struct module *mod)
+{
+    char       buff[LEN_128] = {0};
+    char       mod_path[LEN_128] = {0};
+
+    /* get the full path of modules */
+    sprintf(buff, DEFAULT_MODULE_PATH);
+
+    snprintf(mod_path, LEN_128, "%s/%s.lua", buff, mod->name);
+
+    if (luaL_loadfile(L, mod_path) != 0) {
+        do_debug(LOG_ERR, "load_lua_module: luaL_loadfile module %s err %s\n",
+            mod->name, lua_tostring(L, -1));
+        return;
+    }
+
+    if (lua_pcall(L, 0, 1, 0) != 0) {
+        do_debug(LOG_ERR, "load_lua_module: lua_pcall module %s err %s\n",
+            mod->name, lua_tostring(L, -1));
+        return;
+    }
+
+    if (load_lua_module_register(L, mod) != 0) {
+        return;
+    }
+
+    mod->data_collect = lua_module_data_collect_wrapper;
+    mod->set_st_record = lua_module_set_st_record_wrapper;
+
+    // load lua module to global
+    lua_setglobal(L, mod->name);
+
+    mod->enable = 1;
+    mod->spec = 0;
+    do_debug(LOG_DEBUG, "load_modules: load new module '%s' to mods\n", mod_path);
+
+    return;
+}
