<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Blog ^A Jianing YANG&#039;s</title>
	<atom:link href="http://blog.jianingy.com/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.jianingy.com</link>
	<description>About Linux, System Administration and Hacks</description>
	<lastBuildDate>Fri, 06 Apr 2012 12:23:49 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>Linux UTF-8 环境下 mount vfat 格式文件系统</title>
		<link>http://blog.jianingy.com/2012/04/linux-utf-8-%e7%8e%af%e5%a2%83%e4%b8%8b-mount-vfat-%e6%a0%bc%e5%bc%8f%e6%96%87%e4%bb%b6%e7%b3%bb%e7%bb%9f/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=linux-utf-8-%25e7%258e%25af%25e5%25a2%2583%25e4%25b8%258b-mount-vfat-%25e6%25a0%25bc%25e5%25bc%258f%25e6%2596%2587%25e4%25bb%25b6%25e7%25b3%25bb%25e7%25bb%259f</link>
		<comments>http://blog.jianingy.com/2012/04/linux-utf-8-%e7%8e%af%e5%a2%83%e4%b8%8b-mount-vfat-%e6%a0%bc%e5%bc%8f%e6%96%87%e4%bb%b6%e7%b3%bb%e7%bb%9f/#comments</comments>
		<pubDate>Fri, 06 Apr 2012 12:19:52 +0000</pubDate>
		<dc:creator>Jianing YANG</dc:creator>
				<category><![CDATA[Linux]]></category>

		<guid isPermaLink="false">http://blog.jianingy.com/?p=996</guid>
		<description><![CDATA[中文不会出乱码的mount： sudo mount -t vfat -o codepage=936,iocharset=utf8 /dev/sdb usbdisk]]></description>
			<content:encoded><![CDATA[<p>中文不会出乱码的mount：</p>
<pre>
sudo mount -t vfat -o codepage=936,iocharset=utf8 /dev/sdb usbdisk
</pre></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.jianingy.com/2012/04/linux-utf-8-%e7%8e%af%e5%a2%83%e4%b8%8b-mount-vfat-%e6%a0%bc%e5%bc%8f%e6%96%87%e4%bb%b6%e7%b3%bb%e7%bb%9f/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>承包了 test-ipv6.com 的镜像</title>
		<link>http://blog.jianingy.com/2012/03/%e6%89%bf%e5%8c%85%e4%ba%86%e4%b8%80%e4%b8%aa-test-ipv6-com-%e7%9a%84%e9%95%9c%e5%83%8f/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=%25e6%2589%25bf%25e5%258c%2585%25e4%25ba%2586%25e4%25b8%2580%25e4%25b8%25aa-test-ipv6-com-%25e7%259a%2584%25e9%2595%259c%25e5%2583%258f</link>
		<comments>http://blog.jianingy.com/2012/03/%e6%89%bf%e5%8c%85%e4%ba%86%e4%b8%80%e4%b8%aa-test-ipv6-com-%e7%9a%84%e9%95%9c%e5%83%8f/#comments</comments>
		<pubDate>Thu, 15 Mar 2012 09:44:00 +0000</pubDate>
		<dc:creator>Jianing YANG</dc:creator>
				<category><![CDATA[IPv6]]></category>
		<category><![CDATA[Activities]]></category>

		<guid isPermaLink="false">http://blog.jianingy.com/?p=989</guid>
		<description><![CDATA[花了两天时间在自己的 Linode 上搭建了一个 test-ipv6.com 的镜像。域名是： http://cn.test-ipv6.com, http://jp.test-ipv6.com 以及 http://test.china-ipv6.net。 目前正在和 YuTing 同学一起始对 test-ipv6.com 进行中文翻译。计划在6月6号 之前完成。]]></description>
			<content:encoded><![CDATA[<p>花了两天时间在自己的 Linode 上搭建了一个 test-ipv6.com 的镜像。域名是： <a href="http://cn.test-ipv6.com">http://cn.test-ipv6.com</a>, <a href="http://jp.test-ipv6.com">http://jp.test-ipv6.com</a> 以及 <a href="http://test.china-ipv6.net">http://test.china-ipv6.net</a>。 </p>
<p> 目前正在和 YuTing 同学一起始对 test-ipv6.com 进行中文翻译。计划在6月6号 之前完成。 </p>
]]></content:encoded>
			<wfw:commentRss>http://blog.jianingy.com/2012/03/%e6%89%bf%e5%8c%85%e4%ba%86%e4%b8%80%e4%b8%aa-test-ipv6-com-%e7%9a%84%e9%95%9c%e5%83%8f/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>运维及编码主力键盘</title>
		<link>http://blog.jianingy.com/2012/03/%e8%bf%90%e7%bb%b4%e5%8f%8a%e7%bc%96%e7%a0%81%e4%b8%bb%e5%8a%9b%e9%94%ae%e7%9b%98/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=%25e8%25bf%2590%25e7%25bb%25b4%25e5%258f%258a%25e7%25bc%2596%25e7%25a0%2581%25e4%25b8%25bb%25e5%258a%259b%25e9%2594%25ae%25e7%259b%2598</link>
		<comments>http://blog.jianingy.com/2012/03/%e8%bf%90%e7%bb%b4%e5%8f%8a%e7%bc%96%e7%a0%81%e4%b8%bb%e5%8a%9b%e9%94%ae%e7%9b%98/#comments</comments>
		<pubDate>Mon, 12 Mar 2012 14:58:53 +0000</pubDate>
		<dc:creator>Jianing YANG</dc:creator>
				<category><![CDATA[Keyboard]]></category>

		<guid isPermaLink="false">http://blog.jianingy.com/?p=982</guid>
		<description><![CDATA[Happy Hacking Professional 2 - White 左侧 Control 键极大增加 Emacs 以及 Bash 操作效率。同时因为没有方向键，手也老实多了，光标移动全部靠主键盘区快捷键完成。]]></description>
			<content:encoded><![CDATA[<p>Happy Hacking Professional 2 - White</p>
<p><a href="http://www.flickr.com/photos/57090628@N02/6806367983/" title="My HHKB Pro2 by jianingy.yang, on Flickr"><img src="http://farm8.staticflickr.com/7034/6806367983_7bc6bd8c57.jpg" width="500" height="333" alt="My HHKB Pro2"></a></p>
<p>左侧 Control 键极大增加 Emacs 以及 Bash 操作效率。同时因为没有方向键，手也老实多了，光标移动全部靠主键盘区快捷键完成。</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.jianingy.com/2012/03/%e8%bf%90%e7%bb%b4%e5%8f%8a%e7%bc%96%e7%a0%81%e4%b8%bb%e5%8a%9b%e9%94%ae%e7%9b%98/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>bugfix: proxychains: conflicts between localnet and proxydns solved.</title>
		<link>http://blog.jianingy.com/2012/03/bugfix-proxychains-conflicts-between-localnet-and-proxydns-solved/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=bugfix-proxychains-conflicts-between-localnet-and-proxydns-solved</link>
		<comments>http://blog.jianingy.com/2012/03/bugfix-proxychains-conflicts-between-localnet-and-proxydns-solved/#comments</comments>
		<pubDate>Mon, 12 Mar 2012 14:00:00 +0000</pubDate>
		<dc:creator>Jianing YANG</dc:creator>
				<category><![CDATA[Proxychains]]></category>
		<category><![CDATA[Activities]]></category>

		<guid isPermaLink="false">http://blog.jianingy.com/?p=970</guid>
		<description><![CDATA[2012-03-12 Mon When proxydns subnet falls into localnet's range, DNS can not be resolved anymore. These commits fixed this problem by applying true_connect() to proxydns subnet. Please refer to commits: https://github.com/jianingy/proxychains/commit/b6746997d2cc6a7b581982e1b478a6b26f096d71 https://github.com/jianingy/proxychains/commit/6dda28a2c8f32f72f2e857637fcec6d3a24edda7]]></description>
			<content:encoded><![CDATA[<p> <span class="timestamp-wrapper"> <span class="timestamp">2012-03-12 Mon</span></span> When proxydns subnet falls into localnet's range, DNS can not be resolved anymore. These commits fixed this problem by applying true_connect() to proxydns subnet. </p>
<p> Please refer to commits: </p>
<ul>
<li><a href="https://github.com/jianingy/proxychains/commit/b6746997d2cc6a7b581982e1b478a6b26f096d71">https://github.com/jianingy/proxychains/commit/b6746997d2cc6a7b581982e1b478a6b26f096d71</a> </li>
<li>
<p>   <a href="https://github.com/jianingy/proxychains/commit/6dda28a2c8f32f72f2e857637fcec6d3a24edda7">https://github.com/jianingy/proxychains/commit/6dda28a2c8f32f72f2e857637fcec6d3a24edda7</a> </p>
</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://blog.jianingy.com/2012/03/bugfix-proxychains-conflicts-between-localnet-and-proxydns-solved/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>rxvt-unicode-chinese has been updated to 9.15</title>
		<link>http://blog.jianingy.com/2012/03/rxvt-unicode-chinese-has-been-updated-to-9-15/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=rxvt-unicode-chinese-has-been-updated-to-9-15</link>
		<comments>http://blog.jianingy.com/2012/03/rxvt-unicode-chinese-has-been-updated-to-9-15/#comments</comments>
		<pubDate>Sun, 11 Mar 2012 16:00:00 +0000</pubDate>
		<dc:creator>Jianing YANG</dc:creator>
				<category><![CDATA[rxvt-unicode-chinese]]></category>
		<category><![CDATA[Activities]]></category>

		<guid isPermaLink="false">http://blog.jianingy.com/?p=977</guid>
		<description><![CDATA[2012-03-12 Mon rxvt-unicode-chinese has been updated to 9.15. Just updated to 9.15 source, no big deal.]]></description>
			<content:encoded><![CDATA[<p> <span class="timestamp-wrapper"> <span class="timestamp">2012-03-12 Mon</span></span> rxvt-unicode-chinese has been updated to 9.15. </p>
<p> Just updated to 9.15 source, no big deal. </p>
]]></content:encoded>
			<wfw:commentRss>http://blog.jianingy.com/2012/03/rxvt-unicode-chinese-has-been-updated-to-9-15/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>通过 Linode 接入 IPv6 网络</title>
		<link>http://blog.jianingy.com/2012/03/%e9%80%9a%e8%bf%87-linode-%e6%8e%a5%e5%85%a5-ipv6-%e7%bd%91%e7%bb%9c/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=%25e9%2580%259a%25e8%25bf%2587-linode-%25e6%258e%25a5%25e5%2585%25a5-ipv6-%25e7%25bd%2591%25e7%25bb%259c</link>
		<comments>http://blog.jianingy.com/2012/03/%e9%80%9a%e8%bf%87-linode-%e6%8e%a5%e5%85%a5-ipv6-%e7%bd%91%e7%bb%9c/#comments</comments>
		<pubDate>Thu, 01 Mar 2012 16:00:00 +0000</pubDate>
		<dc:creator>Jianing YANG</dc:creator>
				<category><![CDATA[IPv6]]></category>

		<guid isPermaLink="false">http://blog.jianingy.com/?p=963</guid>
		<description><![CDATA[在 The World IPv6 Launch Day 前夕，Linode 日本机房也完成了对IPv6的支持。 虽然初始配置每人只有一个 IPv6 的地址，但可以通过 Ticket 向 Linode 申请 /56 或者 /64 的地址段。 我在今天完成了 /56 地址段的申请, 申请过程大致如下： Hi, dear linode stuff Thanks for all your previous work. Now I am able to route a /64 subnet. Here, I request a /56 subnet routed to my linode so that I [...]]]></description>
			<content:encoded><![CDATA[<p>在 The World IPv6 Launch Day 前夕，Linode 日本机房也完成了对IPv6的支持。 虽然初始配置每人只有一个 IPv6 的地址，但可以通过 Ticket 向 Linode 申请 /56 或者 /64 的地址段。 </p>
<p> 我在今天完成了 /56 地址段的申请, 申请过程大致如下： </p>
<pre class="example">Hi, dear linode stuff

Thanks for all your previous work. Now I am able to route a /64
subnet. Here, I request a /56 subnet routed to my linode so that I can
enable my (and friends') home computers connecting to IPv6 network.

-----------------------------------------------------------------------

...

-----------------------------------------------------------------------

Hello,

I have changed your /64 block to a /56 block, routing it to the same
address of 2400:8900::F03C:91FF:FE93:D67A.

Your new block is: 2400:8900:e001:0000::/56

If there is anything else we can do for you, please let us know!

Regards,
Nick
</pre>
<p> 地址分配好后，需要重启下 Linode 的机器路由才会生效。随后，我配置了 radvd 用来将一个 /64 的地址段宣告给所有 OpenVPN 的连接, </p>
<pre class="example">interface tap100
{
        AdvSendAdvert on;
        MinRtrAdvInterval 30;
        MaxRtrAdvInterval 100;
        prefix 2400:8900:e001:00ff::/64
        {
                AdvOnLink on;
                AdvAutonomous on;
                AdvRouterAddr off;
        };

};
</pre>
<p> 接下来又配置了 zebra ，把一个 /64 的地址段路由到家里去。 </p>
<pre class="example">interface tap100
  ipv6 address 2400:8900:e001:ff::1/64
ipv6 route 2400:8900:e001:1::/64 2400:8900:e001:ff::2
ip forwarding
ipv6 forwarding
</pre>
<p> 最后，在家里的 RouterBoard 上，宣告下 2400:8900:e001:1::/64 的地址再添 加一个IPv6的默认路由就大功告成了。 </p>
<pre class="example">/ipv6 address
add address=2400:8900:e001:ff::2/64 advertise=yes disabled=no eui-64=no interface=ovpn-out1
add address=2400:8900:e001:1::/64 advertise=yes disabled=no eui-64=no
interface=ether5

/ipv6 route
add disabled=no distance=1 dst-address=2000::/3 gateway=2400:8900:e001:ff::1 scope=30 target-scope=10
</pre>
<p> 当然出于安全考虑后续还有很多防火墙规则需要设置。（特别注意：在 Linux 上 v6 版本的防火墙程序叫做 ip6tables 。） </p>
<p> 通过 Linode 日本机房接入 IPv6 速度要比 he.net 快很多， </p>
<pre class="example">## ping via linode
netbook:~ $ ping6 -c 4 ipv6.google.com
PING ipv6.google.com(2404:6800:8005::67) 56 data bytes
64 bytes from 2404:6800:8005::67: icmp_seq=1 ttl=52 time=215 ms
64 bytes from 2404:6800:8005::67: icmp_seq=2 ttl=52 time=216 ms
64 bytes from 2404:6800:8005::67: icmp_seq=3 ttl=52 time=219 ms
64 bytes from 2404:6800:8005::67: icmp_seq=4 ttl=52 time=214 ms

--- ipv6.google.com ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 3000ms
rtt min/avg/max/mdev = 214.558/216.463/219.397/1.895 ms

## ping via he.net
gao-yang:~ $ ping6 -c 4 ipv6.google.com
PING ipv6.google.com(2404:6800:8005::67) 56 data bytes
64 bytes from 2404:6800:8005::67: icmp_seq=0 ttl=56 time=555 ms
64 bytes from 2404:6800:8005::67: icmp_seq=1 ttl=56 time=613 ms
64 bytes from 2404:6800:8005::67: icmp_seq=2 ttl=56 time=594 ms
64 bytes from 2404:6800:8005::67: icmp_seq=3 ttl=56 time=587 ms

--- ipv6.google.com ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 2999ms
rtt min/avg/max/mdev = 555.706/587.928/613.258/20.788 ms, pipe 2
</pre>
<p> Jfesler test-ipv6.com 上的测试数据： </p>
<p> <a href="http://www.flickr.com/photos/57090628@N02/6950909179/"><img src="http://farm8.staticflickr.com/7193/6950909179_342cfa868b.jpg" alt="6950909179_342cfa868b.jpg"/></a> </p>
<p> 想让最后一项测试通过需要一个能支持查询 IPv6-Only DNS 的 Local DNS，比 如：OpenDNS 提供的 2620:0:ccc::2，2620:0:ccd::2 。 </p>
]]></content:encoded>
			<wfw:commentRss>http://blog.jianingy.com/2012/03/%e9%80%9a%e8%bf%87-linode-%e6%8e%a5%e5%85%a5-ipv6-%e7%bd%91%e7%bb%9c/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Noppoo Choc (MX Brown)</title>
		<link>http://blog.jianingy.com/2012/02/noppoo-choc-mx-brown/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=noppoo-choc-mx-brown</link>
		<comments>http://blog.jianingy.com/2012/02/noppoo-choc-mx-brown/#comments</comments>
		<pubDate>Sun, 26 Feb 2012 13:21:14 +0000</pubDate>
		<dc:creator>Jianing YANG</dc:creator>
				<category><![CDATA[Keyboard]]></category>

		<guid isPermaLink="false">http://blog.jianingy.com/?p=960</guid>
		<description><![CDATA[从同学那里借来玩的 Noppoo Choc 茶轴。发现键盘上居然有个叫 “Switch Lock” 的开关，用来切换左侧的 Control 和 Caps Lock。看来也是考虑到了广大Emacser的需求了。只是这个键盘不能在 MacOSX 下面正常工作，十分不爽啊。]]></description>
			<content:encoded><![CDATA[<p>从同学那里借来玩的 Noppoo Choc 茶轴。发现键盘上居然有个叫 “Switch Lock” 的开关，用来切换左侧的 Control 和 Caps Lock。看来也是考虑到了广大Emacser的需求了。只是这个键盘不能在 MacOSX 下面正常工作，十分不爽啊。</p>
<p><a title="Noppoo Choc (MX Brown) by jianingy.yang, on Flickr" href="http://www.flickr.com/photos/57090628@N02/6931319493/"><img src="http://farm8.staticflickr.com/7041/6931319493_c4b22dc891.jpg" alt="Noppoo Choc (MX Brown)" width="500" height="333" /></a></p>
<p><a title="Noppoo Choc (MX Brown) by jianingy.yang, on Flickr" href="http://www.flickr.com/photos/57090628@N02/6785199746/"><img src="http://farm8.staticflickr.com/7197/6785199746_78cd297b4d.jpg" alt="Noppoo Choc (MX Brown)" width="500" height="333" /></a></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.jianingy.com/2012/02/noppoo-choc-mx-brown/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Ocaml Godi</title>
		<link>http://blog.jianingy.com/2012/02/ocaml-godi/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=ocaml-godi</link>
		<comments>http://blog.jianingy.com/2012/02/ocaml-godi/#comments</comments>
		<pubDate>Fri, 24 Feb 2012 16:00:00 +0000</pubDate>
		<dc:creator>Jianing YANG</dc:creator>
				<category><![CDATA[Ocaml]]></category>
		<category><![CDATA[ocaml ocaml-godi]]></category>

		<guid isPermaLink="false">http://blog.jianingy.com/?p=939</guid>
		<description><![CDATA[用 Godi 安装 Ocaml 扩展库 (Library) godi_console 是用来管理库的工具。他被的存放在 /opt/godi/sbin/godi_console 下面。 查看所有扩展库 $ godi_console -list -names 这命令速度奇慢，长时间看不到输出请别慌。 安装扩展库 用 godi_console -list 找到合适的扩展后，用 perform 指令安装。比如： $ godi_console perform -build godi-curl 扩展库基本使用方法 在普通 Ocaml 程序里面可以用 topfind 及其 "directives" 来加载扩展库， 例如： #use "topfind" ;; #require "yojson";; #require "curl" ;; 扩展库加载后，直接用 Open 就可以打开里面的模块了。 在编译 Ocaml 程序是，要去掉上面的 "directives" 。然后采用 ocamlfind 程序来编译，例如： [...]]]></description>
			<content:encoded><![CDATA[<div id="outline-container-1" class="outline-2">
<h2 id="sec-1">用 Godi 安装 Ocaml 扩展库 (Library)</h2>
<div class="outline-text-2" id="text-1">
<p> godi_console 是用来管理库的工具。他被的存放在 <code>/opt/godi/sbin/godi_console</code> 下面。 </p>
</p>
</div>
<div id="outline-container-1-1" class="outline-3">
<h3 id="sec-1-1">查看所有扩展库</h3>
<div class="outline-text-3" id="text-1-1">
<pre class="src src-sh">$ godi_console -list -names
</pre>
<p> 这命令速度奇慢，长时间看不到输出请别慌。 </p>
</p>
</div>
</div>
<div id="outline-container-1-2" class="outline-3">
<h3 id="sec-1-2">安装扩展库</h3>
<div class="outline-text-3" id="text-1-2">
<p> 用 <code>godi_console -list</code> 找到合适的扩展后，用 <code>perform</code> 指令安装。比如： </p>
<pre class="src src-sh">$ godi_console perform -build godi-curl
</pre>
</p>
</div>
</div>
</div>
<div id="outline-container-2" class="outline-2">
<h2 id="sec-2">扩展库基本使用方法</h2>
<div class="outline-text-2" id="text-2">
<p> 在普通 Ocaml 程序里面可以用 <code>topfind</code> 及其 "directives" 来加载扩展库， 例如： </p>
<pre class="src src-ocaml"><span class="org-preprocessor">#use</span> <span class="org-string">"topfind"</span> <span class="org-tuareg-font-lock-operator">;;</span>
<span class="org-preprocessor">#require</span> <span class="org-string">"yojson"</span><span class="org-tuareg-font-lock-operator">;;</span>
<span class="org-preprocessor">#require</span> <span class="org-string">"curl"</span> <span class="org-tuareg-font-lock-operator">;;</span>
</pre>
<p> 扩展库加载后，直接用 <code>Open</code> 就可以打开里面的模块了。 </p>
<p> 在编译 Ocaml 程序是，要去掉上面的 "directives" 。然后采用 <code>ocamlfind</code> 程序来编译，例如： </p>
<pre class="src src-sh">ocamlfind opt -package yojson -package curl -package unix -package pcre -c search.ml
ocamlfind opt -package yojson -package curl -package unix -package pcre -linkpkg -o search search.cmx
</pre>
</p>
</div>
<div id="outline-container-2-1" class="outline-3">
<h3 id="sec-2-1">常见问题</h3>
<div class="outline-text-3" id="text-2-1">    </div>
<div id="outline-container-2-1-1" class="outline-4">
<h4 id="sec-2-1-1">提示 "#require" 不是有效的 "directive"</h4>
<div class="outline-text-4" id="text-2-1-1">
<p> 基本都是因为 #use "topfind" 没有加上 </p>
</p>
</div>
</div>
</div>
</div>
<div id="outline-container-3" class="outline-2">
<h2 id="sec-3">主流扩展及其特点</h2>
<div class="outline-text-2" id="text-3">    </div>
<div id="outline-container-3-1" class="outline-3">
<h3 id="sec-3-1">JSON 解析</h3>
<div class="outline-text-3" id="text-3-1">
<p> Google 出来的什么 <code>json-wheel</code>, <code>json-static</code> 都是已经过时的东西了。貌 似现在 ocamler 都是用 <code>yojson</code> 和 <code>atdgen</code> 的。 </p>
</p>
</div>
<div id="outline-container-3-1-1" class="outline-4">
<h4 id="sec-3-1-1">yojson</h4>
<div class="outline-text-4" id="text-3-1-1">
<p> <code>yojson</code> 返回一个可遍历的数据结构，递归搞下就OK了。实例如下： </p>
<pre class="src src-json">{
    <span class="org-string">"num"</span>: 1,
    <span class="org-string">"result"</span>: [
        {
            <span class="org-string">".cn"</span>: <span class="org-string">"xxxxxxxx.site"</span>,
            <span class="org-string">".id"</span>: 123456,
            <span class="org-string">".manifest"</span>: <span class="org-string">"vm_server"</span>,
            <span class="org-string">"capex"</span>: <span class="org-string">""</span>,
            <span class="org-string">"clone_mac"</span>: <span class="org-string">"00:12:34:56:78:AB"</span>,
            <span class="org-string">"clone_profile"</span>: <span class="org-string">"vm_app_server"</span>,
            <span class="org-string">"description"</span>: <span class="org-string">""</span>,
            <span class="org-string">"dns_ip"</span>: <span class="org-string">"172.16.0.1"</span>,
            <span class="org-string">"hw_cpu"</span>: <span class="org-string">""</span>,
            <span class="org-string">"hw_harddisk"</span>: <span class="org-string">""</span>,
            <span class="org-string">"hw_mem"</span>: <span class="org-string">""</span>,
            <span class="org-string">"is_clone"</span>: <span class="org-string">""</span>,
            <span class="org-string">"manufacturer"</span>: <span class="org-string">"DELL"</span>,
            <span class="org-string">"model"</span>: <span class="org-string">"vm"</span>,
            <span class="org-string">"node_tag"</span>: <span class="org-string">""</span>,
            <span class="org-string">"nodegroup"</span>: <span class="org-string">"group1"</span>,
            <span class="org-string">"nodename"</span>: <span class="org-string">"xxxxxxxx.site"</span>,
            <span class="org-string">"opex"</span>: <span class="org-string">""</span>,
            <span class="org-string">"os"</span>: <span class="org-string">"rhel_5u4_64"</span>,
            <span class="org-string">"rack"</span>: <span class="org-string">"S1-T1-Z1"</span>,
            <span class="org-string">"site"</span>: <span class="org-string">"S1"</span>,
            <span class="org-string">"state"</span>: <span class="org-string">"working_offline"</span>,
            <span class="org-string">"vmparent"</span>: <span class="org-string">"yyyyyyyy.site"</span>
        }
    ],
    <span class="org-string">"start"</span>: 0,
    <span class="org-string">"total"</span>: 0
}
</pre>
<pre class="src src-ocaml"><span class="org-tuareg-font-lock-governing">let</span> <span class="org-variable-name">json_obj </span><span class="org-tuareg-font-lock-operator">=</span> <span class="org-string">"&lt;THE ABOVE JSON STRING&gt;"</span> <span class="org-tuareg-font-lock-governing">in</span>
<span class="org-tuareg-font-lock-governing">let</span> <span class="org-function-name">get_value</span><span class="org-variable-name"> key obj </span><span class="org-tuareg-font-lock-operator">=</span>
  <span class="org-keyword">match</span> obj <span class="org-keyword">with</span>
            `Assoc<span class="org-tuareg-font-lock-operator">(</span>l<span class="org-tuareg-font-lock-operator">)</span> <span class="org-tuareg-font-lock-operator">-&gt;</span> <span class="org-type">List</span>.find <span class="org-tuareg-font-lock-operator">(</span><span class="org-keyword">fun</span> <span class="org-tuareg-font-lock-operator">(</span><span class="org-variable-name">k</span><span class="org-tuareg-font-lock-operator">,</span><span class="org-variable-name"> v</span><span class="org-tuareg-font-lock-operator">)</span><span class="org-variable-name"> </span><span class="org-tuareg-font-lock-operator">-&gt;</span> k <span class="org-tuareg-font-lock-operator">=</span> key<span class="org-tuareg-font-lock-operator">)</span> l
    <span class="org-tuareg-font-lock-operator">|</span> _ <span class="org-tuareg-font-lock-operator">-&gt;</span> key<span class="org-tuareg-font-lock-operator">,</span> `String<span class="org-tuareg-font-lock-operator">(</span><span class="org-string">""</span><span class="org-tuareg-font-lock-operator">)</span> <span class="org-tuareg-font-lock-governing">in</span>
<span class="org-tuareg-font-lock-governing">let</span> <span class="org-variable-name">_</span><span class="org-tuareg-font-lock-operator">,</span><span class="org-variable-name"> nodes </span><span class="org-tuareg-font-lock-operator">=</span> get_value <span class="org-string">"result"</span> json_obj <span class="org-tuareg-font-lock-governing">in</span>
<span class="org-tuareg-font-lock-governing">let</span> <span class="org-tuareg-font-lock-governing">rec</span> <span class="org-function-name">map_result</span><span class="org-variable-name"> acc item </span><span class="org-tuareg-font-lock-operator">=</span>
  <span class="org-keyword">match</span> item <span class="org-keyword">with</span>
            `List<span class="org-tuareg-font-lock-operator">(</span>hd <span class="org-tuareg-font-lock-operator">::</span> tl<span class="org-tuareg-font-lock-operator">)</span> <span class="org-tuareg-font-lock-operator">-&gt;</span> map_result <span class="org-tuareg-font-lock-operator">((</span>get_value <span class="org-string">"nodename"</span> hd<span class="org-tuareg-font-lock-operator">)</span> <span class="org-tuareg-font-lock-operator">::</span> acc<span class="org-tuareg-font-lock-operator">)</span> <span class="org-tuareg-font-lock-operator">(</span>`List tl<span class="org-tuareg-font-lock-operator">)</span>
    <span class="org-tuareg-font-lock-operator">|</span> _ <span class="org-tuareg-font-lock-operator">-&gt;</span> acc <span class="org-tuareg-font-lock-governing">in</span>
<span class="org-tuareg-font-lock-governing">let</span> <span class="org-function-name">add_result</span><span class="org-variable-name"> acc item </span><span class="org-tuareg-font-lock-operator">=</span>
  <span class="org-keyword">match</span> item <span class="org-keyword">with</span>
            _<span class="org-tuareg-font-lock-operator">,</span> `String<span class="org-tuareg-font-lock-operator">(</span>v<span class="org-tuareg-font-lock-operator">)</span> <span class="org-tuareg-font-lock-operator">-&gt;</span> v <span class="org-tuareg-font-lock-operator">::</span> acc
    <span class="org-tuareg-font-lock-operator">|</span> _ <span class="org-tuareg-font-lock-operator">-&gt;</span> acc <span class="org-tuareg-font-lock-governing">in</span>
<span class="org-tuareg-font-lock-governing">let</span> <span class="org-variable-name">result </span><span class="org-tuareg-font-lock-operator">=</span> <span class="org-type">List</span>.fold_left add_result <span class="org-tuareg-font-lock-operator">[]</span> <span class="org-tuareg-font-lock-operator">(</span>map_result <span class="org-tuareg-font-lock-operator">[]</span> nodes<span class="org-tuareg-font-lock-operator">)</span> <span class="org-tuareg-font-lock-governing">in</span>
result <span class="org-tuareg-font-lock-operator">;;</span>
</pre>
</p>
</div>
</div>
</div>
<div id="outline-container-3-2" class="outline-3">
<h3 id="sec-3-2">HTTP 访问</h3>
<div class="outline-text-3" id="text-3-2">
<p> 最开始用了传说中的 <code>netclients</code> 里面的 <code>Http_client</code> 。结果发现下面这个 简单的程序编译出来的二进制文件也要 3.9M 感觉有些不爽。 </p>
<pre class="src src-ocaml"><span class="org-comment-delimiter">(* </span><span class="org-comment">This example shows how to get a file from a HTTP server using</span>
<span class="org-comment"> * the Convenience module.</span>
<span class="org-comment"> *</span>
<span class="org-comment"> * Load this into the toplevel, then:</span>
<span class="org-comment"> * get_and_print "http://www.caml.org/";;</span>
<span class="org-comment"> </span><span class="org-comment-delimiter">*)</span>

<span class="org-tuareg-font-lock-governing">open</span> <span class="org-type">Http_client.Convenience</span><span class="org-tuareg-font-lock-operator">;;</span>

<span class="org-tuareg-font-lock-governing">let</span> <span class="org-function-name">get_and_print</span><span class="org-variable-name"> url </span><span class="org-tuareg-font-lock-operator">=</span>
  <span class="org-tuareg-font-lock-governing">let</span> <span class="org-variable-name">s </span><span class="org-tuareg-font-lock-operator">=</span> http_get url <span class="org-tuareg-font-lock-governing">in</span>
  print_string s<span class="org-tuareg-font-lock-operator">;</span>
  flush stdout
<span class="org-tuareg-font-lock-operator">;;</span>

<span class="org-tuareg-font-lock-governing">let</span><span class="org-variable-name"> </span><span class="org-tuareg-font-lock-operator">()</span><span class="org-variable-name"> </span><span class="org-tuareg-font-lock-operator">=</span>
        get_and_print <span class="org-type">Sys</span>.argv.<span class="org-tuareg-font-lock-operator">(</span>1<span class="org-tuareg-font-lock-operator">)</span> <span class="org-tuareg-font-lock-operator">;;</span>
</pre>
<p> 随后尝试了，Ocaml 版本的 Curl &ndash; ocurl 。由于动态连接了 <code>libcurl</code> ，下 面这个简单的程序编译出来只有 590K+ 。 </p>
<pre class="src src-ocaml"><span class="org-tuareg-font-lock-governing">let</span> <span class="org-function-name">get_and_print</span><span class="org-variable-name"> url </span><span class="org-tuareg-font-lock-operator">=</span>
  <span class="org-tuareg-font-lock-governing">let</span> <span class="org-function-name">http_cb</span><span class="org-variable-name"> acc s </span><span class="org-tuareg-font-lock-operator">=</span>
    <span class="org-type">Buffer</span>.add_string acc s<span class="org-tuareg-font-lock-operator">;</span>
    <span class="org-type">String</span>.length s <span class="org-tuareg-font-lock-governing">in</span>
  <span class="org-tuareg-font-lock-governing">let</span> <span class="org-variable-name">connection </span><span class="org-tuareg-font-lock-operator">=</span> <span class="org-type">Curl</span>.init <span class="org-tuareg-font-lock-operator">()</span> <span class="org-tuareg-font-lock-governing">in</span>
  <span class="org-tuareg-font-lock-governing">let</span> <span class="org-variable-name">b </span><span class="org-tuareg-font-lock-operator">=</span> <span class="org-type">Buffer</span>.create 16384 <span class="org-tuareg-font-lock-governing">in</span>
  <span class="org-type">Curl</span>.setopt connection <span class="org-tuareg-font-lock-operator">(</span><span class="org-type">Curl</span>.CURLOPT_URL url<span class="org-tuareg-font-lock-operator">);</span>
  <span class="org-type">Curl</span>.setopt connection <span class="org-tuareg-font-lock-operator">(</span><span class="org-type">Curl</span>.CURLOPT_WRITEFUNCTION <span class="org-tuareg-font-lock-operator">(</span>http_cb b<span class="org-tuareg-font-lock-operator">));</span>
  <span class="org-type">Curl</span>.perform connection<span class="org-tuareg-font-lock-operator">;</span>
  print_string <span class="org-tuareg-font-lock-operator">(</span><span class="org-type">Buffer</span>.contents b<span class="org-tuareg-font-lock-operator">)</span> <span class="org-tuareg-font-lock-operator">;</span>
  flush stdout <span class="org-tuareg-font-lock-operator">;;</span>

<span class="org-tuareg-font-lock-governing">let</span><span class="org-variable-name"> </span><span class="org-tuareg-font-lock-operator">()</span><span class="org-variable-name"> </span><span class="org-tuareg-font-lock-operator">=</span>
        get_and_print <span class="org-type">Sys</span>.argv.<span class="org-tuareg-font-lock-operator">(</span>1<span class="org-tuareg-font-lock-operator">)</span> <span class="org-tuareg-font-lock-operator">;;</span>
</pre>
<p> 暂时还没有其他方面的比较。不过感觉上 <code>netclients</code> 的易用性似乎要好些。 </p>
</div>
</div>
</div>
]]></content:encoded>
			<wfw:commentRss>http://blog.jianingy.com/2012/02/ocaml-godi/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Emacs GNUS 存储已发送邮件的配置</title>
		<link>http://blog.jianingy.com/2012/01/emacs-gnus-%e5%ad%98%e5%82%a8%e5%b7%b2%e5%8f%91%e9%80%81%e9%82%ae%e4%bb%b6%e7%9a%84%e9%85%8d%e7%bd%ae/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=emacs-gnus-%25e5%25ad%2598%25e5%2582%25a8%25e5%25b7%25b2%25e5%258f%2591%25e9%2580%2581%25e9%2582%25ae%25e4%25bb%25b6%25e7%259a%2584%25e9%2585%258d%25e7%25bd%25ae</link>
		<comments>http://blog.jianingy.com/2012/01/emacs-gnus-%e5%ad%98%e5%82%a8%e5%b7%b2%e5%8f%91%e9%80%81%e9%82%ae%e4%bb%b6%e7%9a%84%e9%85%8d%e7%bd%ae/#comments</comments>
		<pubDate>Mon, 02 Jan 2012 02:17:05 +0000</pubDate>
		<dc:creator>Jianing YANG</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://blog.jianingy.com/2012/01/emacs-gnus-%e5%ad%98%e5%82%a8%e5%b7%b2%e5%8f%91%e9%80%81%e9%82%ae%e4%bb%b6%e7%9a%84%e9%85%8d%e7%bd%ae/</guid>
		<description><![CDATA[(add-to-list 'gnus-secondary-select-methods '(nnfolder "archive")) (setq nnfolder-directory "~/.emacs.d/mail/archive") ;; where to store sentmail (setq gnus-message-archive-method '(nnfolder "archive" (nnfolder-inhibit-expiry t) (nnfolder-active-file "~/.emacs.d/mail/archive/active") (nnfolder-directory "~/.emacs.d/mail/archive"))) gnus-message-archive-method 是用来设置已发送邮件存储位置的。同样的目 录再加入到 gnus-secondary-select-methods 里面，让“已发件”文件夹能在 Group列表里显示。]]></description>
			<content:encoded><![CDATA[<pre class="src src-emacs-lisp">(add-to-list 'gnus-secondary-select-methods '(nnfolder <span class="org-string">"archive"</span>))
(setq nnfolder-directory <span class="org-string">"~/.emacs.d/mail/archive"</span>)
<span class="org-comment-delimiter">;; </span><span class="org-comment">where to store sentmail</span>
(setq gnus-message-archive-method
      '(nnfolder <span class="org-string">"archive"</span>
                 (nnfolder-inhibit-expiry t)
                 (nnfolder-active-file <span class="org-string">"~/.emacs.d/mail/archive/active"</span>)
                 (nnfolder-directory <span class="org-string">"~/.emacs.d/mail/archive"</span>)))
</pre>
<p> <code>gnus-message-archive-method</code> 是用来设置已发送邮件存储位置的。同样的目 录再加入到 <code>gnus-secondary-select-methods</code> 里面，让“已发件”文件夹能在 Group列表里显示。 </p>
]]></content:encoded>
			<wfw:commentRss>http://blog.jianingy.com/2012/01/emacs-gnus-%e5%ad%98%e5%82%a8%e5%b7%b2%e5%8f%91%e9%80%81%e9%82%ae%e4%bb%b6%e7%9a%84%e9%85%8d%e7%bd%ae/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>PostgreSQL查询优化 &#8211; 函数索引</title>
		<link>http://blog.jianingy.com/2011/12/postgresql%e6%9f%a5%e8%af%a2%e4%bc%98%e5%8c%96-%e5%87%bd%e6%95%b0%e7%b4%a2%e5%bc%95/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=postgresql%25e6%259f%25a5%25e8%25af%25a2%25e4%25bc%2598%25e5%258c%2596-%25e5%2587%25bd%25e6%2595%25b0%25e7%25b4%25a2%25e5%25bc%2595</link>
		<comments>http://blog.jianingy.com/2011/12/postgresql%e6%9f%a5%e8%af%a2%e4%bc%98%e5%8c%96-%e5%87%bd%e6%95%b0%e7%b4%a2%e5%bc%95/#comments</comments>
		<pubDate>Fri, 30 Dec 2011 13:51:00 +0000</pubDate>
		<dc:creator>Jianing YANG</dc:creator>
				<category><![CDATA[PostgreSQL]]></category>

		<guid isPermaLink="false">http://blog.jianingy.com/2011/12/postgresql%e6%9f%a5%e8%af%a2%e4%bc%98%e5%8c%96-%e5%87%bd%e6%95%b0%e7%b4%a2%e5%bc%95/</guid>
		<description><![CDATA[nodes表是我用来存储硬件设备的一个表。由于各种硬件设备的属性数量不同，我 采用了HSTORE来进行存储。 Table "public.nodes" Column &#124; Type &#124; Modifiers ----------+------------------------+---------------------------------------------------- id &#124; integer &#124; not null default nextval('nodes_id_seq'::regclass) manifest &#124; character varying(60) &#124; not null cn &#124; character varying(124) &#124; not null value &#124; hstore &#124; depends &#124; integer[] &#124; 其中，value-&#62;'node_tag' 用来存储设备的“应用标签”。为了前段程序处理方便， 他是一个字符串类型的数据。我们采用“&#124;”来分隔不同的标签。例如： ?column? ----------------- &#124;java&#124;pub&#124; 表示该设备拥有两个“应用标签”java 和 pub。 我们的应用，需要通过“应用标签”来进行设备查询。采用如下的语句： select value-&#62;'node_tag' from node_cache where [...]]]></description>
			<content:encoded><![CDATA[<p>nodes表是我用来存储硬件设备的一个表。由于各种硬件设备的属性数量不同，我 采用了HSTORE来进行存储。 </p>
<pre class="example">                                  Table "public.nodes"
  Column  |          Type          |                     Modifiers
----------+------------------------+----------------------------------------------------
 id       | integer                | not null default nextval('nodes_id_seq'::regclass)
 manifest | character varying(60)  | not null
 cn       | character varying(124) | not null
 value    | hstore                 |
 depends  | integer[]              |
</pre>
<p> 其中，value-&gt;'node_tag' 用来存储设备的“应用标签”。为了前段程序处理方便， 他是一个字符串类型的数据。我们采用“|”来分隔不同的标签。例如： </p>
<pre class="example">    ?column?
-----------------
 |java|pub|
</pre>
<p> 表示该设备拥有两个“应用标签”java 和 pub。 </p>
<p> 我们的应用，需要通过“应用标签”来进行设备查询。采用如下的语句： </p>
<pre class="example">select value-&gt;'node_tag' from node_cache where regexp_split_to_array(value-&gt;'node_tag', '\|') @&gt; ARRAY['pub'];
</pre>
<p> 调用查询分析器可以看出，因为使用了顺序搜索，他的性能很差。 </p>
<pre class="example">database=&gt; EXPLAIN ANALYZE  select value-&gt;'node_tag' from node_cache where regexp_split_to_array(value-&gt;'node_tag', '\|') @&gt; ARRAY['pub'];
                                                  QUERY PLAN
---------------------------------------------------------------------------------------------------------------
 Seq Scan on node_cache  (cost=0.00..5505.88 rows=53 width=593) (actual time=106.390..135.642 rows=39 loops=1)
   Filter: (regexp_split_to_array((value -&gt; 'node_tag'::text), '\|'::text) @&gt; '{pub}'::text[])
 Total runtime: 135.677 ms
(3 rows)
</pre>
<p> 万幸的是PostgreSQL提供了可定制的函数索引，我们可以针对 <code>regexp_split_to_array</code> 的结果进行索引。例如： </p>
<pre class="example">CREATE index idx_test_splitted_node_tag on node_cache using gin(regexp_split_to_array(value-&gt;'node_tag', '\|'));
</pre>
<p> 采用GIN倒排索引，查询效率有了显著的提升（135ms vs 0。175ms）, </p>
<pre class="example">database=&gt; explain ANALYZE  select value-&gt;'node_tag' from node_cache where regexp_split_to_array(value-&gt;'node_tag', '\|') @&gt; ARRAY['pub'];
                                                              QUERY PLAN
--------------------------------------------------------------------------------------------------------------------------------------
 Bitmap Heap Scan on node_cache  (cost=12.42..208.36 rows=53 width=593) (actual time=0.055..0.137 rows=39 loops=1)
   Recheck Cond: (regexp_split_to_array((value -&gt; 'node_tag'::text), '\|'::text) @&gt; '{pub}'::text[])
   -&gt;  Bitmap Index Scan on idx_test_splitted_node_tag  (cost=0.00..12.41 rows=53 width=0) (actual time=0.034..0.034 rows=39 loops=1)
         Index Cond: (regexp_split_to_array((value -&gt; 'node_tag'::text), '\|'::text) @&gt; '{pub}'::text[])
 Total runtime: 0.175 ms
(5 rows)
</pre>
]]></content:encoded>
			<wfw:commentRss>http://blog.jianingy.com/2011/12/postgresql%e6%9f%a5%e8%af%a2%e4%bc%98%e5%8c%96-%e5%87%bd%e6%95%b0%e7%b4%a2%e5%bc%95/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

