<?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>子云小筑</title>
	<atom:link href="http://www.imneio.com/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.imneio.com</link>
	<description>Neio Blog</description>
	<lastBuildDate>Fri, 04 Dec 2009 00:32:44 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>NoSQL小记</title>
		<link>http://www.imneio.com/2009/12/nosql/</link>
		<comments>http://www.imneio.com/2009/12/nosql/#comments</comments>
		<pubDate>Thu, 03 Dec 2009 13:01:59 +0000</pubDate>
		<dc:creator>neio</dc:creator>
				<category><![CDATA[前沿理论]]></category>
		<category><![CDATA[生活随笔]]></category>
		<category><![CDATA[ACID]]></category>
		<category><![CDATA[BASE]]></category>
		<category><![CDATA[CAP]]></category>
		<category><![CDATA[HBase]]></category>
		<category><![CDATA[hypertable]]></category>
		<category><![CDATA[Key-Value]]></category>
		<category><![CDATA[NoSQL]]></category>
		<category><![CDATA[RDBMS]]></category>
		<category><![CDATA[RowColumn]]></category>

		<guid isPermaLink="false">http://www.imneio.com/?p=87</guid>
		<description><![CDATA[&#8211;Neio
我是在今年（2009年）夏天的“NoSQL”运动后(链接)才深入将Key-Value型存储方式引入现有的工作中的。早先对Google的Bigtable略有了解，知道其对数据存储思想的影响，但始终没有深入去了解它，所以现在也算是了去了一个遗憾。
我认为，NoSQL运动的意义并不是完全反对SQL，而是在于告诉被关系型数据库(RDBMS)这座宏伟的大山挡住视线的人们，SQL并非唯一的数据存储方式。也就是后来人们说的&#8221;Not Only SQL&#8221;——这一简短精辟的诠释&#8221;NoSQL&#8221;的短语。
目前我使用的Hypertable, HBase（HBase为参照使用），都是基于Bigtable模型的Key-Value型(更准确说是RowColumn型)分布式存储方式。选择它们，也是在于Bigtable盛名之下的缘故。
NoSQL运动中的模型并非Bigtable模型只此一家，而是如同春秋时期的诸子百家，整体呈现出了百家争鸣的局面。
Why NoSQL?
三个关键字：ACID, BASE, CAP
ACID是DBMS中强调的，分别是原子性(Atomicity)、一致性(Consistency)、隔离性(Isolation)、持久性 (Durability)。对于这四个名词不了解的，请参考维基百科对于ACID的描述。总体来说，ACID的目的就是通过事务支持，保证数据的完整性和正确性。
CAP: CAP是一个经验理论，由Brewer所提。三个字母分别是 Consistency, Availability 和 Partition Tolerance的缩写，分别可以翻译为一致性、有效性和网络分离容忍度。三个目标无法兼得，ACID在一致性和有效性卓有成效，而在Partition tolerance上的努力, 则非常艰难。而目前互联网应用情形下的海量数据，将单台计算机的处理能力压榨殆尽，单台计算机上的关系型数据库很难满足应用需求；而如果将关系型数据库的表分割存储在不同的计算机上，其有效性将很难保证。
于是乎，BASE被渐渐从记忆中挖掘出来，渐渐成为hot word。这个名词同样是Brewer所提。分别是英文：Basically Available， Soft-state, Eventual Consistency的缩写，正好与ACID这个缩写在字面上的意思相对应。这个理论认为，只需要满足Eventual Consistency（最终一致性）即可，而且可以是无连接的(Soft-state)。值得一提的是，eBay正是根据BASE的原理设计起架构。有兴趣的朋友可以参考《
BASE: An Acid Alternative》。
这三个名词与 NoSQL什么关系？
NoSQL做的，就是通过降低对数据一致性、完整性的要求，转而偏向于CAP中的A和P，通过增加Tolerance to network partition(P)的支持, 甚至与追求P来达到满足高并发的需求。而这背后，就需要BASE理论的支撑，才敢如此的放肆。因为放弃了对一致性的高要求，只需要满足BASE的Eventual Consistency, 也能最终达到一致。
后记
面向高并发的软件架构，特别是电子商务型的网站，更是要在CAP中三个度量中做取舍。核心的业务需要一致性的保证，偏向于用通过关系型数据库来保证，而一些对于一致性要求不高的数据，通过使用Key-Value型数据存储方式，又可以满足大量访问的要求。
ACID与BASE，这两个中和一下，不正是我们所需要的么？ 所以, Why not NoSQL?
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-
PS. 文章在Draft停留了1个月，一直未完稿。始终还没调整好工作的节奏, 困于工作中啊。
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-
 ]]></description>
			<content:encoded><![CDATA[<p>&#8211;Neio</p>
<p>我是在今年（2009年）夏天的“NoSQL”运动后(<a href="http://www.imneio.com/wp-content/plugins/feed-statistics.php?url=aHR0cDovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9Ob1NRTA==" target=\"_blank\">链接</a>)才深入将Key-Value型存储方式引入现有的工作中的。早先对Google的Bigtable略有了解，知道其对数据存储思想的影响，但始终没有深入去了解它，所以现在也算是了去了一个遗憾。</p>
<p>我认为，NoSQL运动的意义并不是完全反对SQL，而是在于告诉被关系型数据库(RDBMS)这座宏伟的大山挡住视线的人们，SQL并非唯一的数据存储方式。也就是后来人们说的&#8221;Not Only SQL&#8221;——这一简短精辟的诠释&#8221;NoSQL&#8221;的短语。</p>
<p>目前我使用的Hypertable, HBase（HBase为参照使用），都是基于Bigtable模型的Key-Value型(更准确说是RowColumn型)分布式存储方式。选择它们，也是在于Bigtable盛名之下的缘故。</p>
<p>NoSQL运动中的模型并非Bigtable模型只此一家，而是如同春秋时期的诸子百家，整体呈现出了百家争鸣的局面。</p>
<p><strong>Why NoSQL?</strong></p>
<p>三个关键字：ACID, BASE, CAP</p>
<p>ACID是DBMS中强调的，分别是原子性(Atomicity)、一致性(Consistency)、隔离性(Isolation)、持久性 (Durability)。对于这四个名词不了解的，请参考<a href="http://www.imneio.com/wp-content/plugins/feed-statistics.php?url=aHR0cDovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9BQ0lE">维基百科</a>对于ACID的描述。总体来说，ACID的目的就是通过事务支持，保证数据的完整性和正确性。</p>
<p>CAP: CAP是一个经验理论，由Brewer所提。三个字母分别是 <strong>C</strong>onsistency, <strong>A</strong>vailability 和 <strong>P</strong>artition Tolerance的缩写，分别可以翻译为一致性、有效性和网络分离容忍度。<strong>三个目标无法兼得</strong>，ACID在一致性和有效性卓有成效，而在Partition tolerance上的努力, 则非常艰难。而目前互联网应用情形下的海量数据，将单台计算机的处理能力压榨殆尽，单台计算机上的关系型数据库很难满足应用需求；而如果将关系型数据库的表分割存储在不同的计算机上，其有效性将很难保证。</p>
<p>于是乎，BASE被渐渐从记忆中挖掘出来，渐渐成为hot word。这个名词同样是Brewer所提。分别是英文：<strong>B</strong>asically <strong>A</strong>vailable， <strong>S</strong>oft-state, <strong>E</strong>ventual Consistency的缩写，正好与ACID这个缩写在字面上的意思相对应。这个理论认为，只需要满足Eventual Consistency（最终一致性）即可，而且可以是无连接的(Soft-state)。值得一提的是，eBay正是根据BASE的原理设计起架构。有兴趣的朋友可以参考《<br />
<a href="http://www.imneio.com/wp-content/plugins/feed-statistics.php?url=aHR0cDovL3F1ZXVlLmFjbS5vcmcvZGV0YWlsLmNmbT9pZD0xMzk0MTI4">BASE: An Acid Alternative</a>》。</p>
<p>这三个名词与 NoSQL什么关系？</p>
<p>NoSQL做的，就是通过降低对数据一致性、完整性的要求，转而偏向于CAP中的A和P，通过增加Tolerance to network partition(P)的支持, 甚至与追求P来达到满足高并发的需求。而这背后，就需要BASE理论的支撑，才敢如此的放肆。因为放弃了对一致性的高要求，只需要满足BASE的Eventual Consistency, 也能最终达到一致。</p>
<p><strong>后记</strong></p>
<p>面向高并发的软件架构，特别是电子商务型的网站，更是要在CAP中三个度量中做取舍。核心的业务需要一致性的保证，偏向于用通过关系型数据库来保证，而一些对于一致性要求不高的数据，通过使用Key-Value型数据存储方式，又可以满足大量访问的要求。</p>
<p>ACID与BASE，这两个中和一下，不正是我们所需要的么？ 所以, Why not NoSQL?</p>
<p>&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-<br />
PS. 文章在Draft停留了1个月，一直未完稿。始终还没调整好工作的节奏, 困于工作中啊。<br />
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-</p>
 <img src="http://www.imneio.com/wp-content/plugins/feed-statistics.php?view=1&post_id=87" width="1" height="1" style="display: none;" />]]></content:encoded>
			<wfw:commentRss>http://www.imneio.com/2009/12/nosql/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Recruit &#124; 招聘</title>
		<link>http://www.imneio.com/2009/11/recruit/</link>
		<comments>http://www.imneio.com/2009/11/recruit/#comments</comments>
		<pubDate>Mon, 16 Nov 2009 15:41:32 +0000</pubDate>
		<dc:creator>neio</dc:creator>
				<category><![CDATA[生活随笔]]></category>

		<guid isPermaLink="false">http://www.imneio.com/?p=88</guid>
		<description><![CDATA[目前我们公司正在招纳新人，具体情况详见：
http://www.qzqx.net/about/Invite.aspx
公司全名：泉州市视通光电网络有限公司
工作地点：公司总部，福建省泉州市中山中路旁（中心市区）
工作要求：如果你有以下资历之一，非常欢迎你的加盟。
1、GIS应用开发2年或以上经验，且为主要项目负责人；
2、精通算法，懂得数学建模的；熟练掌握C++或C#的优先；
3、拥有5年或以上团队经验，且有担任项目经理经验；
4、拥有企业软件设计5年或以上经验者。
拥有以上其中一项资历者，在我们公司可以找到很好的才华展示机会。
积极进取、勇于创新
有意者请将简历或相关材料发到我的邮箱(neio.zhou~~gmail.com)，也可以直接通过上面的链接地址上的联系方式联系。
 ]]></description>
			<content:encoded><![CDATA[<p>目前我们公司正在招纳新人，具体情况详见：</p>
<p><a href="http://www.imneio.com/wp-content/plugins/feed-statistics.php?url=aHR0cDovL3d3dy5xenF4Lm5ldC9hYm91dC9JbnZpdGUuYXNweA==">http://www.qzqx.net/about/Invite.aspx</a></p>
<p>公司全名：泉州市视通光电网络有限公司<br />
工作地点：公司总部，福建省泉州市中山中路旁（中心市区）<br />
工作要求：如果你有以下资历<strong><span style="color: #ff0000;">之一</span></strong>，非常欢迎你的加盟。</p>
<p>1、GIS应用开发2年或以上经验，<strong>且</strong>为主要项目负责人；<br />
2、精通算法，懂得数学建模的；熟练掌握C++或C#的优先；<br />
3、拥有5年或以上团队经验，且有担任项目经理经验；<br />
4、拥有企业软件设计5年或以上经验者。</p>
<p>拥有以上其中一项资历者，在我们公司可以找到很好的才华展示机会。</p>
<p>积极进取、勇于创新</p>
<p>有意者请将简历或相关材料发到我的邮箱(neio.zhou~~gmail.com)，也可以直接通过上面的链接地址上的联系方式联系。</p>
 <img src="http://www.imneio.com/wp-content/plugins/feed-statistics.php?view=1&post_id=88" width="1" height="1" style="display: none;" />]]></content:encoded>
			<wfw:commentRss>http://www.imneio.com/2009/11/recruit/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Thrift C＃for Hypertable Issue</title>
		<link>http://www.imneio.com/2009/10/thrift-csharp-hypertable-issue/</link>
		<comments>http://www.imneio.com/2009/10/thrift-csharp-hypertable-issue/#comments</comments>
		<pubDate>Thu, 29 Oct 2009 16:31:48 +0000</pubDate>
		<dc:creator>neio</dc:creator>
				<category><![CDATA[经验之谈]]></category>
		<category><![CDATA[C#]]></category>
		<category><![CDATA[CSharp]]></category>
		<category><![CDATA[hypertable]]></category>
		<category><![CDATA[Thrift]]></category>

		<guid isPermaLink="false">http://www.imneio.com/?p=75</guid>
		<description><![CDATA[前言
近日在为Hypertable做一层.NET(C#)的封装，遇到了一个较为严重的问题：用Thrift封装的Hypertable C#客户端在连接Hypertable ThriftBroker的时候被主动断开，造成数据无法读取的现象。
过程
1、用Wireshark检查了TCP封包，观察到在发送第一笔数据后就被Hypertable ThriftBrokeryper主动发送FIN结束了连接，于是后面发送数据就丢掉了，更不用说接收信息；
2、检查Hypertable中的日志，查看到以下信息：
TConnection : transition() Negative Frame Size -2147418111, remote side not using TFramedTransport?
注意到这里可以看出，Hypertable使用了TFramedTransport作为其传输层接口。然而，C＃的Thrift中尚无此接口。

可见, Thrift C#还跟不上其主要语言C＋＋的开发脚步。
3、补充：进一步分析，Hypertable使用的是TNonblockingServer作为其服务的方式，而这个TServer的实现有别与其他TSimpleServer, TThreadedServer等实现，在数据的开头加入了数据长度的数据，也正是这一点造成了数据的不兼容。在C++版本中的Thrift将TNonblockingServer与其他TServer的实现分开，单独生成libthriftnb库。而TFramedTransport，正是建立在TNonblockingSocket之上的。
解决方法
请参考：https://issues.apache.org/jira/browse/THRIFT-210
目前官方的代码版本库中还没有相应的代码，为了方便大家理解，我将TFramedTransport.cs的代码放在这里，遇到同样问题的朋友可以从这里拿代码补充到Thrift中编译：

/**
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements. See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership. The ASF licenses this file
 [...]]]></description>
			<content:encoded><![CDATA[<h2>前言</h2>
<p>近日在为Hypertable做一层.NET(C#)的封装，遇到了一个较为严重的问题：用Thrift封装的Hypertable C#客户端在连接Hypertable ThriftBroker的时候被主动断开，造成数据无法读取的现象。</p>
<h2>过程</h2>
<p>1、用Wireshark检查了TCP封包，观察到在发送第一笔数据后就被Hypertable ThriftBrokeryper主动发送FIN结束了连接，于是后面发送数据就丢掉了，更不用说接收信息；</p>
<p>2、检查Hypertable中的日志，查看到以下信息：<br />
TConnection : transition() Negative Frame Size -2147418111, remote side not using TFramedTransport?<br />
注意到这里可以看出，Hypertable使用了TFramedTransport作为其传输层接口。然而，C＃的Thrift中尚无此接口。<br />
<span id="more-75"></span><br />
可见, Thrift C#还跟不上其主要语言C＋＋的开发脚步。</p>
<p>3、补充：进一步分析，Hypertable使用的是TNonblockingServer作为其服务的方式，而这个TServer的实现有别与其他TSimpleServer, TThreadedServer等实现，在数据的开头加入了数据长度的数据，也正是这一点造成了数据的不兼容。在C++版本中的Thrift将TNonblockingServer与其他TServer的实现分开，单独生成libthriftnb库。而TFramedTransport，正是建立在TNonblockingSocket之上的。</p>
<h2>解决方法</h2>
<p>请参考：<a href="http://www.imneio.com/wp-content/plugins/feed-statistics.php?url=aHR0cHM6Ly9pc3N1ZXMuYXBhY2hlLm9yZy9qaXJhL2Jyb3dzZS9USFJJRlQtMjEw" target=\"_self\">https://issues.apache.org/jira/browse/THRIFT-210</a><br />
目前官方的代码版本库中还没有相应的代码，为了方便大家理解，我将<strong>TFramedTransport.cs</strong>的代码放在这里，遇到同样问题的朋友可以从这里拿代码补充到Thrift中编译：</p>
<pre class="brush: csharp;">
/**
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements. See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership. The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * &quot;License&quot;); 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
 * &quot;AS IS&quot; 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.
 */

using System;
using System.Text;
using Thrift.Transport;

namespace Thrift.Protocol
{
	public class TBinaryProtocol : TProtocol
	{
		protected const uint VERSION_MASK = 0xffff0000;
		protected const uint VERSION_1 = 0x80010000;

		protected bool strictRead_ = false;
		protected bool strictWrite_ = true;

		protected int readLength_;
		protected bool checkReadLength_ = false;

		#region BinaryProtocol Factory
		 /**
		  * Factory
		  */
		  public class Factory : TProtocolFactory {

			  protected bool strictRead_ = false;
			  protected bool strictWrite_ = true;

			  public Factory()
				  :this(false, true)
			  {
			  }

			  public Factory(bool strictRead, bool strictWrite)
			  {
				  strictRead_ = strictRead;
				  strictWrite_ = strictWrite;
			  }

			public TProtocol GetProtocol(TTransport trans) {
			  return new TBinaryProtocol(trans, strictRead_, strictWrite_);
			}
		  }

		#endregion

		public TBinaryProtocol(TTransport trans)
			: this(trans, false, true)
		{
		}

		public TBinaryProtocol(TTransport trans, bool strictRead, bool strictWrite)
			:base(trans)
		{
			strictRead_ = strictRead;
			strictWrite_ = strictWrite;
		}

		#region Write Methods

		public override void WriteMessageBegin(TMessage message)
		{
			if (strictWrite_)
			{
				uint version = VERSION_1 | (uint)(message.Type);
				WriteI32((int)version);
				WriteString(message.Name);
				WriteI32(message.SeqID);
			}
			else
			{
				WriteString(message.Name);
				WriteByte((byte)message.Type);
				WriteI32(message.SeqID);
			}
		}

		public override void WriteMessageEnd()
		{
		}

		public override void WriteStructBegin(TStruct struc)
		{
		}

		public override void WriteStructEnd()
		{
		}

		public override void WriteFieldBegin(TField field)
		{
			WriteByte((byte)field.Type);
			WriteI16(field.ID);
		}

		public override void WriteFieldEnd()
		{
		}

		public override void WriteFieldStop()
		{
			WriteByte((byte)TType.Stop);
		}

		public override void WriteMapBegin(TMap map)
		{
			WriteByte((byte)map.KeyType);
			WriteByte((byte)map.ValueType);
			WriteI32(map.Count);
		}

		public override void WriteMapEnd()
		{
		}

		public override void WriteListBegin(TList list)
		{
			WriteByte((byte)list.ElementType);
			WriteI32(list.Count);
		}

		public override void WriteListEnd()
		{
		}

		public override void WriteSetBegin(TSet set)
		{
			WriteByte((byte)set.ElementType);
			WriteI32(set.Count);
		}

		public override void WriteSetEnd()
		{
		}

		public override void WriteBool(bool b)
		{
			WriteByte(b ? (byte)1 : (byte)0);
		}

		private byte[] bout = new byte[1];
		public override void WriteByte(byte b)
		{
			bout[0] = b;
			trans.Write(bout, 0, 1);
		}

		private byte[] i16out = new byte[2];
		public override void WriteI16(short s)
		{
			i16out[0] = (byte)(0xff &amp; (s &gt;&gt; 8));
			i16out[1] = (byte)(0xff &amp; s);
			trans.Write(i16out, 0, 2);
		}

		private byte[] i32out = new byte[4];
		public override void WriteI32(int i32)
		{
			i32out[0] = (byte)(0xff &amp; (i32 &gt;&gt; 24));
			i32out[1] = (byte)(0xff &amp; (i32 &gt;&gt; 16));
			i32out[2] = (byte)(0xff &amp; (i32 &gt;&gt; 8));
			i32out[3] = (byte)(0xff &amp; i32);
			trans.Write(i32out, 0, 4);
		}

		private byte[] i64out = new byte[8];
		public override void WriteI64(long i64)
		{
			i64out[0] = (byte)(0xff &amp; (i64 &gt;&gt; 56));
			i64out[1] = (byte)(0xff &amp; (i64 &gt;&gt; 48));
			i64out[2] = (byte)(0xff &amp; (i64 &gt;&gt; 40));
			i64out[3] = (byte)(0xff &amp; (i64 &gt;&gt; 32));
			i64out[4] = (byte)(0xff &amp; (i64 &gt;&gt; 24));
			i64out[5] = (byte)(0xff &amp; (i64 &gt;&gt; 16));
			i64out[6] = (byte)(0xff &amp; (i64 &gt;&gt; 8));
			i64out[7] = (byte)(0xff &amp; i64);
			trans.Write(i64out, 0, 8);
		}

		public override void WriteDouble(double d)
		{
			WriteI64(BitConverter.DoubleToInt64Bits(d));
		}

		public override void WriteBinary(byte[] b)
		{
			WriteI32(b.Length);
			trans.Write(b, 0, b.Length);
		}

		#endregion

		#region ReadMethods

		public override TMessage ReadMessageBegin()
		{
			TMessage message = new TMessage();
			int size = ReadI32();
			if (size &lt; 0)
			{
				uint version = (uint)size &amp; VERSION_MASK;
				if (version != VERSION_1)
				{
					throw new TProtocolException(TProtocolException.BAD_VERSION, &quot;Bad version in ReadMessageBegin: &quot; + version);
				}
				message.Type = (TMessageType)(size &amp; 0x000000ff);
				message.Name = ReadString();
				message.SeqID = ReadI32();
			}
			else
			{
				if (strictRead_)
				{
					throw new TProtocolException(TProtocolException.BAD_VERSION, &quot;Missing version in readMessageBegin, old client?&quot;);
				}
				message.Name = ReadStringBody(size);
				message.Type = (TMessageType)ReadByte();
				message.SeqID = ReadI32();
			}
			return message;
		}

		public override void ReadMessageEnd()
		{
		}

		public override TStruct ReadStructBegin()
		{
			return new TStruct();
		}

		public override void ReadStructEnd()
		{
		}

		public override TField ReadFieldBegin()
		{
			TField field = new TField();
			field.Type = (TType)ReadByte();

			if (field.Type != TType.Stop)
			{
				field.ID = ReadI16();
			}

			return field;
		}

		public override void ReadFieldEnd()
		{
		}

		public override TMap ReadMapBegin()
		{
			TMap map = new TMap();
			map.KeyType = (TType)ReadByte();
			map.ValueType = (TType)ReadByte();
			map.Count = ReadI32();

			return map;
		}

		public override void ReadMapEnd()
		{
		}

		public override TList ReadListBegin()
		{
			TList list = new TList();
			list.ElementType = (TType)ReadByte();
			list.Count = ReadI32();

			return list;
		}

		public override void ReadListEnd()
		{
		}

		public override TSet ReadSetBegin()
		{
			TSet set = new TSet();
			set.ElementType = (TType)ReadByte();
			set.Count = ReadI32();

			return set;
		}

		public override void ReadSetEnd()
		{
		}

		public override bool ReadBool()
		{
			return ReadByte() == 1;
		}

		private byte[] bin = new byte[1];
		public override byte ReadByte()
		{
			ReadAll(bin, 0, 1);
			return bin[0];
		}

		private byte[] i16in = new byte[2];
		public override short ReadI16()
		{
			ReadAll(i16in, 0, 2);
			return (short)(((i16in[0] &amp; 0xff) &lt;&lt; 8 ) | ((i16in[1] &amp; 0xff)));
		}

		private byte[] i32in = new byte[4];
		public override int ReadI32()
		{
			ReadAll(i32in, 0, 4);
			return (int)(((i32in[0] &amp; 0xff) &lt;&lt; 24) | ((i32in[1] &amp; 0xff) &lt;&lt; 16) | ((i32in[2] &amp; 0xff) &lt;&lt; 8 ) | ((i32in[3] &amp; 0xff)));
		}

		private byte[] i64in = new byte[8];
		public override long ReadI64()
		{
			ReadAll(i64in, 0, 8);
			return (long)(((long)(i64in[0] &amp; 0xff) &lt;&lt; 56) | ((long)(i64in[1] &amp; 0xff) &lt;&lt; 48 ) | ((long)(i64in[2] &amp; 0xff ) &lt;&lt;   40 ) |  ((long)(i64in[3] &amp; 0xff) &lt;&lt; 32) |
				((long)(i64in[4] &amp; 0xff) &lt;&lt; 24) | ((long)(i64in[5] &amp; 0xff) &lt;&lt; 16) | ((long)(i64in[6] &amp; 0xff)  &lt;&lt;  8  ) | ((long)(i64in[7] &amp; 0xff)));
		}

		public override double ReadDouble()
		{
			return BitConverter.Int64BitsToDouble(ReadI64());
		}

		public void SetReadLength(int readLength)
		{
			readLength_ = readLength;
			checkReadLength_ = true;
		}

		protected void CheckReadLength(int length)
		{
			if (checkReadLength_)
			{
				readLength_ -= length;
				if (readLength_ &lt; 0)
				{
					throw new Exception(&quot;Message length exceeded: &quot; + length);
				}
			}
		}

		public override byte[] ReadBinary()
		{
			int size = ReadI32();
			CheckReadLength(size);
			byte[] buf = new byte[size];
			trans.ReadAll(buf, 0, size);
			return buf;
		}
		private  string ReadStringBody(int size)
		{
			CheckReadLength(size);
			byte[] buf = new byte[size];
			trans.ReadAll(buf, 0, size);
			return Encoding.UTF8.GetString(buf);
		}

		private int ReadAll(byte[] buf, int off, int len)
		{
			CheckReadLength(len);
			return trans.ReadAll(buf, off, len);
		}

		#endregion
	}
}
</pre>
<p>下面是解释如何使用TFramedTransport：</p>
<pre class="brush: csharp;">
TSocket socket = new TSocket(&quot;127.0.0.1&quot;, 38080);
TTransport trans = new TFramedTransport(socket);
TProtocol protocol = new TBinaryProtocol(trans);
HqlService.Client client = new HqlService.Client(protocol);
</pre>
<p>&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-</p>
 <img src="http://www.imneio.com/wp-content/plugins/feed-statistics.php?view=1&post_id=75" width="1" height="1" style="display: none;" />]]></content:encoded>
			<wfw:commentRss>http://www.imneio.com/2009/10/thrift-csharp-hypertable-issue/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Thrift简介</title>
		<link>http://www.imneio.com/2009/10/thrift-intro/</link>
		<comments>http://www.imneio.com/2009/10/thrift-intro/#comments</comments>
		<pubDate>Mon, 26 Oct 2009 08:33:49 +0000</pubDate>
		<dc:creator>neio</dc:creator>
				<category><![CDATA[经验之谈]]></category>
		<category><![CDATA[Introduction]]></category>
		<category><![CDATA[Thrift]]></category>

		<guid isPermaLink="false">http://www.imneio.com/?p=65</guid>
		<description><![CDATA[Thrift是一个跨语言服务部署框架，最初由Facebook于2007年开发，后于2008年进入Apache孵化器(Apache Incubator)。
类似于SOAP，COM 和CORBA，Thrift通过定义一个中间定义语言和Thrift代码生成工具，生成指定语言的代码。目前，Thrift支持C++,Java, Python, PHP, Ruby, Erlang, Perl, Haskell, C#, Cocoa, Smalltalk和OCaml的代码生成。
简单分析其机理，Thrift就是实现C/S模式，通过代码生成工具将接口定义文件生成服务器端和客户端代码（可以为不同语言），从而实现服务端和客户端跨语言的支持。
Thrift可以分为传输层和协议层：
1、传输层定义了数据的传输方式，可以为TCP/IP传输，内存共享或者文件共享等形式；
2、协议层定义了数据的传输格式，可以为二进制流或者XML等形式。
简单例子：
中间语言定义：

struct UserProfile {
1: i32 uid,
2: string name,
3: string blurb
}
service UserStorage {
void store(1: UserProfile user),
UserProfile retrieve(1: i32 uid)
}

Python客户端代码：

# Make an object
up = UserProfile(uid=1,
                 name=&#34;Mark Slee&#34;,
     [...]]]></description>
			<content:encoded><![CDATA[<p>Thrift是一个跨语言服务部署框架，最初由Facebook于2007年开发，后于2008年进入Apache孵化器(Apache Incubator)。</p>
<p>类似于SOAP，COM 和CORBA，Thrift通过定义一个中间定义语言和Thrift代码生成工具，生成指定语言的代码。目前，Thrift支持C++,Java, Python, PHP, Ruby, Erlang, Perl, Haskell, C#, Cocoa, Smalltalk和OCaml的代码生成。</p>
<p>简单分析其机理，Thrift就是实现C/S模式，通过代码生成工具将接口定义文件生成服务器端和客户端代码（可以为不同语言），从而实现服务端和客户端跨语言的支持。</p>
<p>Thrift可以分为传输层和协议层：</p>
<p>1、传输层定义了数据的传输方式，可以为TCP/IP传输，内存共享或者文件共享等形式；<br />
2、协议层定义了数据的传输格式，可以为二进制流或者XML等形式。</p>
<p>简单例子：</p>
<p>中间语言定义：</p>
<pre class="brush: plain;">
struct UserProfile {
1: i32 uid,
2: string name,
3: string blurb
}
service UserStorage {
void store(1: UserProfile user),
UserProfile retrieve(1: i32 uid)
}
</pre>
<p>Python客户端代码：</p>
<pre class="brush: python;">
# Make an object
up = UserProfile(uid=1,
                 name=&quot;Mark Slee&quot;,
                 blurb=&quot;I'll find something to put here.&quot;)

# Talk to a server via TCP sockets, using a binary protocol
transport = TSocket.TSocket(&quot;localhost&quot;, 9090)
transport.open()
protocol = TBinaryProtocol.TBinaryProtocol(transport)

# Use the service we already defined
service = UserStorage.Client(protocol)
service.store(up)

# Retrieve something as well
up2 = service.retrieve(2)
</pre>
<p>服务器端代码：</p>
<pre class="brush: cpp;">
class UserStorageHandler : virtual public UserStorageIf {
 public:
  UserStorageHandler() {
    // Your initialization goes here
  }

  void store(const UserProfile&amp; user) {
    // Your implementation goes here
    printf(&quot;store\n&quot;);
  }

  void retrieve(UserProfile&amp; _return, const int32_t uid) {
    // Your implementation goes here
    printf(&quot;retrieve\n&quot;);
  }
};

int main(int argc, char **argv) {
  int port = 9090;
  shared_ptr&lt;UserStorageHandler&gt; handler(new UserStorageHandler());
  shared_ptr&lt;TProcessor&gt; processor(new UserStorageProcessor(handler));
  shared_ptr&lt;TServerTransport&gt; serverTransport(new TServerSocket(port));
  shared_ptr&lt;TTransportFactory&gt; transportFactory(new TBufferedTransportFactory());
  shared_ptr&lt;TProtocolFactory&gt; protocolFactory(new TBinaryProtocolFactory());
  TSimpleServer server(processor, serverTransport, transportFactory, protocolFactory);
  server.serve();
  return 0;
}
</pre>
<p><strong>参考资料</strong></p>
<p>1.<a href="http://www.imneio.com/wp-content/plugins/feed-statistics.php?url=IGh0dHA6Ly9pbmN1YmF0b3IuYXBhY2hlLm9yZy90aHJpZnQ=" target=\"_blank\"> http://incubator.apache.org/thrift</a></p>
 <img src="http://www.imneio.com/wp-content/plugins/feed-statistics.php?view=1&post_id=65" width="1" height="1" style="display: none;" />]]></content:encoded>
			<wfw:commentRss>http://www.imneio.com/2009/10/thrift-intro/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>First C++ Programming Experience with Hypertable(A)</title>
		<link>http://www.imneio.com/2009/10/hypertable_cpp_a/</link>
		<comments>http://www.imneio.com/2009/10/hypertable_cpp_a/#comments</comments>
		<pubDate>Sun, 25 Oct 2009 05:31:33 +0000</pubDate>
		<dc:creator>neio</dc:creator>
				<category><![CDATA[经验之谈]]></category>
		<category><![CDATA[boost]]></category>
		<category><![CDATA[freebase]]></category>
		<category><![CDATA[hypertable]]></category>
		<category><![CDATA[linux]]></category>
		<category><![CDATA[ubuntu]]></category>

		<guid isPermaLink="false">http://www.imneio.com/?p=55</guid>
		<description><![CDATA[前言
目前正在为Hypertable做一层封装，使之通过ZeroMQ或RabbitMQ提供一个通用数据访问接口。
说来蛮郁闷的，编译一个Hypertable的example耗费了我一天半的时间。一来，网速慢，下载boost, thrift, log4cpp等库，耗费了很多时间；二来，没有在Linux下做过项目。
下面我以example里面的freebase作为例子，说明编译环境的配。
编译Freebase例子
一、环境
Ubuntu 8.10
hypertable 0.9.2.7  （hypertable-0.9.2.7-linux-i386.deb）
二、编译所需库
1. libboost1.40-dev
注意: Ubuntu 8.10上的libboost-dev是1.34的版本，需要另外找1.4的，否则编译的时候会出现 undefined reference to boost::system:: 之类的错误。
可以用一下两种方式解决：
一是找debian的官方源，然后用apt-get install的方式安装:
在sources.list下面添加:
deb http://ftp2.de.debian.org/debian unstable main contrib non-free
然后运行：
sudo apt-get update
sudo apt-get install libboost1.40-all-dev
若出现没有公钥(NO_PUBKEY)的错误，请参考这里解决。
二是下载boost的deb包后安装;
三是从Boost官方网站下载源代码来编译。
2.配置CMakeList.txt
以下是我根据我的环境配置的CMakeList.txt的内容，请读者根据自己的环境调整。
include_directories( ./
/usr/include/boost/
/usr/include/log4cpp/
/usr/local/include
/opt/hypertable/current/include
/usr/include/thrift
)
link_directories(
/opt/hypertable/current/lib/
/usr/local/lib/
/usr/lib/
)
add_executable(freebase_load freebase_load.cc freebase_parser.cc)
target_link_libraries(
freebase_load
libHyperThrift.a
libHypertable.a
libHyperComm.a
libHyperspace.a
libHyperCommon.a
libHyperTools.a
libHyperDfsBroker.a
libHyperDfsCmds.a
libHyperRanger.a
libsigar-x86-linux.so
libdb_cxx-4.6.so
libboost_filesystem.so
libboost_iostreams.so
libboost_program_options.so
libboost_regex.so
libboost_system.so
libboost_signals.so
libboost_thread.so
libboost_date_time.so
libexpat.so
libgcc_s.so
libthrift.so
libthriftnb.so
libstdc++.so
libpthread.so
libz.so
liblog4cpp.so
libtcmalloc_minimal.so
libdl.so
libevent.so
libcurses.so
)
3.为程序编写配置文件
在程序运行目录相对地址（例如:/opt/hyperspace/current/examples/freebase）下，添加conf/hypertable.cfg文件。
往里面添加配置内容，例如我的：
Hypersapce.Master.Host=localhost
Hyperspace.Master.Port=38040
Hyperspace.Master.Dir=hyperspace
Hyperspace.Master.Workers=20
4. 编译运行
首先，在hypertable中添加freebase的数据结构，即create-table-freebase.hql里面的内容。
然后，运行以下几句编译和运行
$sudo cmake ./
$sudo make
$./freebase  aircraft_model.tsv
至此，试验大功告成。接接下去就是开始设计自己的分装了。
 ]]></description>
			<content:encoded><![CDATA[<h2>前言</h2>
<p>目前正在为Hypertable做一层封装，使之通过ZeroMQ或RabbitMQ提供一个通用数据访问接口。</p>
<p>说来蛮郁闷的，编译一个Hypertable的example耗费了我一天半的时间。一来，网速慢，下载boost, thrift, log4cpp等库，耗费了很多时间；二来，没有在Linux下做过项目。</p>
<p>下面我以example里面的freebase作为例子，说明编译环境的配。</p>
<h2>编译Freebase例子</h2>
<p>一、环境</p>
<p>Ubuntu 8.10</p>
<p>hypertable 0.9.2.7  （<a href="http://www.imneio.com/wp-content/plugins/feed-statistics.php?url=aHR0cDovL3BhY2thZ2UuaHlwZXJ0YWJsZS5vcmcv" target=\"_blank\">hypertable-0.9.2.7-linux-i386.deb</a>）<span id="more-55"></span></p>
<p>二、编译所需库</p>
<p>1. libboost1.40-dev</p>
<p><strong>注意</strong>: Ubuntu 8.10上的libboost-dev是1.34的版本，需要另外找1.4的，否则编译的时候会出现 undefined reference to boost::system:: 之类的错误。</p>
<p>可以用一下两种方式解决：</p>
<p>一是找debian的官方源，然后用apt-get install的方式安装:</p>
<blockquote><p>在sources.list下面添加:</p>
<p>deb http://ftp2.de.debian.org/debian unstable main contrib non-free</p>
<p>然后运行：</p>
<p>sudo apt-get update</p>
<p>sudo apt-get install libboost1.40-all-dev</p>
<p>若出现<strong>没有公钥(NO_PUBKEY)</strong>的错误，请参考<a href="http://www.imneio.com/wp-content/plugins/feed-statistics.php?url=aHR0cDovL3d3dy5pbW5laW8uY29tLzIwMDkvMTAvdWJ1bnR1LXB1YmtleS8=" target=\"_blank\">这里</a>解决。</p></blockquote>
<p>二是下载boost的deb包后安装;</p>
<p>三是从Boost官方网站下载源代码来编译。</p>
<p>2.配置CMakeList.txt</p>
<p>以下是我根据我的环境配置的CMakeList.txt的内容，请读者根据自己的环境调整。</p>
<blockquote><p>include_directories( ./<br />
/usr/include/boost/<br />
/usr/include/log4cpp/<br />
/usr/local/include<br />
/opt/hypertable/current/include<br />
/usr/include/thrift<br />
)</p>
<p>link_directories(<br />
/opt/hypertable/current/lib/<br />
/usr/local/lib/<br />
/usr/lib/<br />
)</p>
<p>add_executable(freebase_load freebase_load.cc freebase_parser.cc)</p>
<p>target_link_libraries(</p>
<p>freebase_load<br />
libHyperThrift.a<br />
libHypertable.a<br />
libHyperComm.a<br />
libHyperspace.a<br />
libHyperCommon.a<br />
libHyperTools.a<br />
libHyperDfsBroker.a<br />
libHyperDfsCmds.a<br />
libHyperRanger.a<br />
libsigar-x86-linux.so<br />
libdb_cxx-4.6.so<br />
libboost_filesystem.so<br />
libboost_iostreams.so<br />
libboost_program_options.so<br />
libboost_regex.so<br />
libboost_system.so<br />
libboost_signals.so<br />
libboost_thread.so<br />
libboost_date_time.so<br />
libexpat.so<br />
libgcc_s.so<br />
libthrift.so<br />
libthriftnb.so<br />
libstdc++.so<br />
libpthread.so<br />
libz.so<br />
liblog4cpp.so<br />
libtcmalloc_minimal.so<br />
libdl.so<br />
libevent.so<br />
libcurses.so</p>
<p>)</p></blockquote>
<p>3.为程序编写配置文件</p>
<p>在程序运行目录相对地址（例如:/opt/hyperspace/current/examples/freebase）下，添加conf/hypertable.cfg文件。</p>
<p>往里面添加配置内容，例如我的：</p>
<blockquote><p>Hypersapce.Master.Host=localhost</p>
<p>Hyperspace.Master.Port=38040</p>
<p>Hyperspace.Master.Dir=hyperspace</p>
<p>Hyperspace.Master.Workers=20</p></blockquote>
<p>4. 编译运行</p>
<p>首先，在hypertable中添加freebase的数据结构，即create-table-freebase.hql里面的内容。</p>
<p>然后，运行以下几句编译和运行</p>
<p>$sudo cmake ./</p>
<p>$sudo make</p>
<p>$./freebase  aircraft_model.tsv</p>
<p>至此，试验大功告成。接接下去就是开始设计自己的分装了。</p>
 <img src="http://www.imneio.com/wp-content/plugins/feed-statistics.php?view=1&post_id=55" width="1" height="1" style="display: none;" />]]></content:encoded>
			<wfw:commentRss>http://www.imneio.com/2009/10/hypertable_cpp_a/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Ubuntu源出现公钥问题的解决方式</title>
		<link>http://www.imneio.com/2009/10/ubuntu-pubkey/</link>
		<comments>http://www.imneio.com/2009/10/ubuntu-pubkey/#comments</comments>
		<pubDate>Sun, 25 Oct 2009 05:16:04 +0000</pubDate>
		<dc:creator>neio</dc:creator>
				<category><![CDATA[经验之谈]]></category>
		<category><![CDATA[Debian]]></category>
		<category><![CDATA[gpg]]></category>
		<category><![CDATA[NO_PUBKEY]]></category>
		<category><![CDATA[pubkey]]></category>
		<category><![CDATA[ubuntu]]></category>
		<category><![CDATA[公钥]]></category>

		<guid isPermaLink="false">http://www.imneio.com/?p=59</guid>
		<description><![CDATA[Ubuntu等debian系统使用中，若添加第三方源，在apt-get update的时候可能会出现NO_PUBKEY的错误提示。
解决方式：
根据apt-get update出现的pubkey提示，运行以下两句可以解决问题：
$gpg &#8211;keyserver keyserver.ubuntu.com -recv-key [所提示的公钥]
$gpg &#8211;export &#8211;armor [所提示的公钥] &#124; sudo apt-key add -
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;
added on 2009.10.27
or
sudo apt-key adv &#8211;recv-keys &#8211;keyserver keyserver.ubuntu.com [YOURKEY]
[THE END]
 ]]></description>
			<content:encoded><![CDATA[<p>Ubuntu等debian系统使用中，若添加第三方源，在apt-get update的时候可能会出现NO_PUBKEY的错误提示。</p>
<h3>解决方式：</h3>
<p>根据apt-get update出现的pubkey提示，运行以下两句可以解决问题：</p>
<p><strong>$gpg &#8211;keyserver keyserver.ubuntu.com -recv-key [所提示的公钥]</strong></p>
<p><strong>$gpg &#8211;export &#8211;armor [所提示的公钥] | sudo apt-key add -</strong></p>
<p>&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;</p>
<p>added on 2009.10.27</p>
<p>or<br />
<strong>sudo apt-key adv &#8211;recv-keys &#8211;keyserver keyserver.ubuntu.com [YOURKEY]</strong></p>
<p>[THE END]</p>
 <img src="http://www.imneio.com/wp-content/plugins/feed-statistics.php?view=1&post_id=59" width="1" height="1" style="display: none;" />]]></content:encoded>
			<wfw:commentRss>http://www.imneio.com/2009/10/ubuntu-pubkey/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>在Linux下使用Google拼音输入法</title>
		<link>http://www.imneio.com/2009/10/google-pinyin-ubuntu/</link>
		<comments>http://www.imneio.com/2009/10/google-pinyin-ubuntu/#comments</comments>
		<pubDate>Wed, 21 Oct 2009 15:25:51 +0000</pubDate>
		<dc:creator>neio</dc:creator>
				<category><![CDATA[经验之谈]]></category>
		<category><![CDATA[Debian]]></category>
		<category><![CDATA[Google]]></category>
		<category><![CDATA[GooglePinyin]]></category>
		<category><![CDATA[linux]]></category>
		<category><![CDATA[Pinyin]]></category>
		<category><![CDATA[ubuntu]]></category>
		<category><![CDATA[谷歌]]></category>
		<category><![CDATA[谷歌拼音输入法]]></category>

		<guid isPermaLink="false">http://www.imneio.com/?p=53</guid>
		<description><![CDATA[习惯于Windows下的搜狗输入法，真觉得在Linux下的拼音输入法非常不顺手。
近日才恍然发现某位仁兄移植了Android下的谷歌输入法到Linux下(链接)，于是赶紧弄下来体验了一把。总体感觉顺手很多，当然也有少许的BUG（例如有时候输入完拼音后，直接只显示了拼音原文而不是汉字）。
下面是安装步骤（需要自己编译）：
A. 获取代码：
$ git clone git://github.com/tchaikov/scim-googlepinyin.git
$ cd scim-googlepinyin.git
B. 编译前提：
上面给的链接里面有介绍怎么编译的，但少提了几个必需组件，这里列一下：
* autotools-dev
* libgtk2.0-dev
* libscim-dev
* libtool
* automake1.9
用下面命令看看是不是安装了，如果没有，会自动帮你安装上：
$ aptitude install autotools-dev libgtk2.0-dev libscim-dev libtool automake1.9
C. 编译：
记住系统必须先存在SCIM（没有的话 sudo apt-get install scim 一下）
$ ./autogen.sh
$ make
$ sudo make install
大功告成，重启下SCIM然后就能体验了。
 ]]></description>
			<content:encoded><![CDATA[<p>习惯于Windows下的搜狗输入法，真觉得在Linux下的拼音输入法非常不顺手。</p>
<p>近日才恍然发现某位仁兄移植了Android下的谷歌输入法到Linux下(<a href="http://www.imneio.com/wp-content/plugins/feed-statistics.php?url=aHR0cDovL2NvZGUuZ29vZ2xlLmNvbS9wL3NjaW0tZ29vZ2xlcGlueWluLw==" target=\"_blank\">链接</a>)，于是赶紧弄下来体验了一把。总体感觉顺手很多，当然也有少许的BUG（例如有时候输入完拼音后，直接只显示了拼音原文而不是汉字）。</p>
<p>下面是安装步骤（需要自己编译）：</p>
<p>A. 获取代码：</p>
<blockquote><p>$ git clone git://github.com/tchaikov/scim-googlepinyin.git<br />
$ cd scim-googlepinyin.git</p></blockquote>
<p>B. 编译前提：</p>
<p>上面给的链接里面有介绍怎么编译的，但少提了几个必需组件，这里列一下：</p>
<blockquote><p>* autotools-dev<br />
* libgtk2.0-dev<br />
* libscim-dev<br />
* libtool<br />
* automake1.9</p></blockquote>
<p>用下面命令看看是不是安装了，如果没有，会自动帮你安装上：</p>
<blockquote><p>$ aptitude install autotools-dev libgtk2.0-dev libscim-dev libtool automake1.9</p></blockquote>
<p>C. 编译：<br />
记住系统必须先存在SCIM（没有的话 sudo apt-get install scim 一下）</p>
<blockquote><p>$ ./autogen.sh<br />
$ make<br />
$ sudo make install</p></blockquote>
<p>大功告成，重启下SCIM然后就能体验了。</p>
 <img src="http://www.imneio.com/wp-content/plugins/feed-statistics.php?view=1&post_id=53" width="1" height="1" style="display: none;" />]]></content:encoded>
			<wfw:commentRss>http://www.imneio.com/2009/10/google-pinyin-ubuntu/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>在.NET上使用ZeroMQ</title>
		<link>http://www.imneio.com/2009/10/zeromq_in_dotnet/</link>
		<comments>http://www.imneio.com/2009/10/zeromq_in_dotnet/#comments</comments>
		<pubDate>Sat, 17 Oct 2009 09:03:24 +0000</pubDate>
		<dc:creator>neio</dc:creator>
				<category><![CDATA[架构设计]]></category>
		<category><![CDATA[经验之谈]]></category>
		<category><![CDATA[.NET]]></category>
		<category><![CDATA[0MQ]]></category>
		<category><![CDATA[Bus]]></category>
		<category><![CDATA[C#]]></category>
		<category><![CDATA[CLR]]></category>
		<category><![CDATA[dotNET]]></category>
		<category><![CDATA[Erlang]]></category>
		<category><![CDATA[RabbitMQ]]></category>
		<category><![CDATA[ZeroMQ]]></category>
		<category><![CDATA[消息中间件]]></category>
		<category><![CDATA[消息总线]]></category>

		<guid isPermaLink="false">http://www.imneio.com/?p=43</guid>
		<description><![CDATA[前言
最近在设计一个Web系统（公司在建项目，故保密不能详述），要满足高并发，高访问量、高可靠性的需求，又会涉及到多种业务外部系统，甚至业务可能是可“热插拔”的形式，同时又要最求成本最低。
考虑到总总因素，排除了使用Oracle数据库，以及其他各种商业组件的方案；同时又由于公司项目很多，缺乏人手来自己开发一些组件，故除了业务系统是自己开发外，其他基本上采用了清一色的开源软件。 由于业务比较复杂，同时大量使用了各种开源系统，会使用到C++, Java, Erlang, C#, PHP等众多语言。故设计用系统总线(Bus)来作为消息的介质，协调整体的运行，而这条总线的性能和特性也将关系到系统的命运。
RabbitMQ or ZeroMQ?
经过比较选型，从多语言的支持的角度，最后筛选得到RabbitMQ和ZeroMQ两个选择。
RabbitMQ是采用Erlang开发的，支持完善的AMQP协议；ZeroMQ使用C语言开发，重点在于效率；两者均有多语言支持，其中ZeroMQ支持得较多。
比较看, RabbitMQ支持的AMQP协议，较为完整和复杂；而ZeroMQ的接口极为简单。速度上，还未对亲自对两者做压力测试。从网上的资料看，RabbitMQ较慢，几十个并发以内，延时为几十毫秒，但当客户端达到1000个并发的时候，速度就无法容忍了（参考）；ZeroMQ上则据称可以达到13毫米延时和高达每秒4.1兆次传递（参考, 国内需要翻墙才能访问）。如果队列较多的话，RabbitMQ很容易把内存耗尽，而ZeroMQ则把队列内容保存在发送端。
故最终还是决定选择了ZeroMQ，然后在上面加一层我自己的封装，作为Web系统的消息总线。
在.NET上使用ZeroMQ
ZeroMQ的.NET封装很简单，基本上是来自C-API的，但有所简化。使用上，由于习惯了在C#里面用强类型约束，API上的int类型让我感觉封装得&#8221;非常不.NET&#8221;。
首先要明确下ZeroMQ的几个概念：
1. Exchange &#38; Queue：Exchange 是系统数据交换的基础，Queue是消息通道，当Exchange与Queue绑定后，向Exchange提交消息，就会流到其绑定的Queue(s)中。
2. 接收端创建一个Queue后，就能从里面获取内容。
3.Zmq_server: 这个是ZeroMQ消息的核心程序，负责调度消息，是ZeroMQ系统的&#8221;CPU&#8221;。
由于是轻量级的，在.NET下使用ZeroMQ也非常简单：
1. libclrzmq.dll 是封装过的.NET客户端，引用之。运行的时候记得把zeromq的bin下的其他dll也复制过去。
2. 运行zmq_server.exe服务：
zmq_server --port 5555
其中，5555是服务的端口。也可以用&#8211;config来指定配置文件，这里不详述。
3. 消息发送与接收：
发送端：

Zmq q = new Zmq();
q.Open(&#34;127.0.0.1:5555&#34;);
int ex = q.CreateExchange(&#34;EX1&#34;, null,  Zmq.SCOPE_LOCAL, Zmq.STYLE_LOAD_BALANCING);
Zmq.Bind(&#34;EX1&#34;,&#34;Q1&#34;, null, null);
Zmq.Send(ex, new byte[]{1,2,3,5}, false);

接收端：

Zmq q = new Zmq();
q.Open(&#34;127.0.0.1:5555&#34;);
int ex = q.CreateQueue(&#34;Q1&#34;,  Zmq.SCOPE_GLOBAL, &#34;127.0.0.1:5556&#34;,Zmq.NO_LIMIT,Zmq.NO_LIMIT, Zmq.NO_SWAP);
int outType;
byte[] data;
Zmq.Receive( out data, out outType, true);//阻塞方式接收

上面代码中，STYLE_LOAD_BALANCING表示数据被一个接收端接收到后就结束，若改为STYLE_DATA_DISTRIBUTION则表示数据将会发送到每个接收端上。
此外，根据官方的文档：
SCOPE_LOCAL：
Local [...]]]></description>
			<content:encoded><![CDATA[<h2>前言</h2>
<p>最近在设计一个Web系统（公司在建项目，故保密不能详述），要满足高并发，高访问量、高可靠性的需求，又会涉及到多种业务外部系统，甚至业务可能是可“热插拔”的形式，同时又要最求成本最低。</p>
<p>考虑到总总因素，排除了使用Oracle数据库，以及其他各种商业组件的方案；同时又由于公司项目很多，缺乏人手来自己开发一些组件，故除了业务系统是自己开发外，其他基本上采用了清一色的开源软件。 由于业务比较复杂，同时大量使用了各种开源系统，会使用到C++, Java, Erlang, C#, PHP等众多语言。故设计用<strong>系统总线(Bus)</strong>来作为消息的介质，协调整体的运行，而这条总线的性能和特性也将关系到系统的命运。</p>
<h2>RabbitMQ or ZeroMQ?</h2>
<p>经过比较选型，从多语言的支持的角度，最后筛选得到RabbitMQ和ZeroMQ两个选择。</p>
<p>RabbitMQ是采用Erlang开发的，支持完善的AMQP协议；ZeroMQ使用C语言开发，重点在于效率；两者均有多语言支持，其中ZeroMQ支持得较多。</p>
<p>比较看, RabbitMQ支持的AMQP协议，较为完整和复杂；而ZeroMQ的接口极为简单。速度上，还未对亲自对两者做压力测试。从网上的资料看，RabbitMQ较慢，几十个并发以内，延时为几十毫秒，但当客户端达到1000个并发的时候，速度就无法容忍了（<a title=\"RabbitMQ perfomance testing &amp; troubles\" href="http://www.imneio.com/wp-content/plugins/feed-statistics.php?url=aHR0cDovL2ZvcnVtLnRyYXBleGl0Lm9yZy9tYWlsaW5nbGlzdHMvdmlld3RvcGljLnBocD9wPTQyODkwJmFtcDtzaWQ9Y2I3OGE5MmFiNTBhZGVmYmY2MGUzNzcwYzBiYTdlOWI=" target=\"_blank\">参考</a>）；ZeroMQ上则据称可以达到13毫米延时和高达每秒4.1兆次传递（<a href="http://www.imneio.com/wp-content/plugins/feed-statistics.php?url=aHR0cDovL3d3dy56ZXJvbXEub3JnLw==" target=\"_blank\">参考</a>, 国内需要翻墙才能访问）。如果队列较多的话，RabbitMQ很容易把内存耗尽，而ZeroMQ则把队列内容保存在发送端。</p>
<p>故最终还是决定选择了ZeroMQ，然后在上面加一层我自己的封装，作为Web系统的消息总线。</p>
<h2>在.NET上使用ZeroMQ</h2>
<p>ZeroMQ的.NET封装很简单，基本上是来自C-API的，但有所简化。使用上，由于习惯了在C#里面用强类型约束，API上的int类型让我感觉封装得&#8221;<strong>非常不.NET&#8221;</strong>。</p>
<p>首先要明确下ZeroMQ的几个概念：<span id="more-43"></span></p>
<p>1. Exchange &amp; Queue：Exchange 是系统数据交换的基础，Queue是消息通道，当Exchange与Queue绑定后，向Exchange提交消息，就会流到其绑定的Queue(s)中。</p>
<p>2. 接收端创建一个Queue后，就能从里面获取内容。</p>
<p>3.Zmq_server: 这个是ZeroMQ消息的核心程序，负责调度消息，是ZeroMQ系统的&#8221;CPU&#8221;。</p>
<p>由于是轻量级的，在.NET下使用ZeroMQ也非常简单：</p>
<p>1. libclrzmq.dll 是封装过的.NET客户端，引用之。运行的时候记得把zeromq的bin下的其他dll也复制过去。</p>
<p>2. 运行zmq_server.exe服务：</p>
<pre class="brush: ruby;">zmq_server --port 5555</pre>
<p>其中，5555是服务的端口。也可以用&#8211;config来指定配置文件，这里不详述。</p>
<p>3. 消息发送与接收：</p>
<p>发送端：</p>
<pre class="brush: csharp;">
Zmq q = new Zmq();
q.Open(&quot;127.0.0.1:5555&quot;);
int ex = q.CreateExchange(&quot;EX1&quot;, null,  Zmq.SCOPE_LOCAL, Zmq.STYLE_LOAD_BALANCING);
Zmq.Bind(&quot;EX1&quot;,&quot;Q1&quot;, null, null);
Zmq.Send(ex, new byte[]{1,2,3,5}, false);
</pre>
<p>接收端：</p>
<pre class="brush: csharp;">
Zmq q = new Zmq();
q.Open(&quot;127.0.0.1:5555&quot;);
int ex = q.CreateQueue(&quot;Q1&quot;,  Zmq.SCOPE_GLOBAL, &quot;127.0.0.1:5556&quot;,Zmq.NO_LIMIT,Zmq.NO_LIMIT, Zmq.NO_SWAP);
int outType;
byte[] data;
Zmq.Receive( out data, out outType, true);//阻塞方式接收
</pre>
<p>上面代码中，STYLE_LOAD_BALANCING表示数据被一个接收端接收到后就结束，若改为STYLE_DATA_DISTRIBUTION则表示数据将会发送到每个接收端上。<br />
此外，根据官方的文档：<br />
<strong>SCOPE_LOCAL</strong>：<br />
Local scope means that the object (exchange or queue) is visible only within the engine that created it.<br />
<strong>SCOPE_PROCESS</strong>:<br />
Process scope means that the object is visible to all the engines within the process registered with the same dispatcher object.<br />
<strong>SCOPE_GLOBAL</strong>:<br />
Global scope means that the object is visible to all the 0MQ processes registered with the same zmq_server.</p>
<p>注意事项，上述程序的接收端需要先启动，然后再启动发送端，否则发送端在BindQ1的时候将找不到队列而出错。</p>
 <img src="http://www.imneio.com/wp-content/plugins/feed-statistics.php?view=1&post_id=43" width="1" height="1" style="display: none;" />]]></content:encoded>
			<wfw:commentRss>http://www.imneio.com/2009/10/zeromq_in_dotnet/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>加法分解</title>
		<link>http://www.imneio.com/2009/10/reduce/</link>
		<comments>http://www.imneio.com/2009/10/reduce/#comments</comments>
		<pubDate>Mon, 12 Oct 2009 14:53:52 +0000</pubDate>
		<dc:creator>neio</dc:creator>
				<category><![CDATA[算法设计]]></category>
		<category><![CDATA[Reduce]]></category>
		<category><![CDATA[加法分解]]></category>
		<category><![CDATA[多项式]]></category>
		<category><![CDATA[算法]]></category>

		<guid isPermaLink="false">http://www.imneio.com/?p=34</guid>
		<description><![CDATA[今天在首尔大学读硕士的老同学问了我一个简单的算法，他的要求描述是：
多项式参数的穷举：
1*A1+2*A2+3*A3+&#8230;+n*An=n
n是固定值，要打印出所有A的排列。
太久没写算法，发现自己在一天的班上下来后，思考能力已经退化到可怕的境界了。最后花了2个多小时才完全写好，通过测试。
简要分析一下（以5为例子）：
5 = 5 * 1
5 = 5 * 0 + 4 * 1 + 1 * 1
5 = 5 * 0 + 4 * 0 + 3 * 1 + 2 * 1
5 = 5 * 0 + 4 * 0 + 3 * 1 + 2 * 0 + 1 * 2
5 = 5 [...]]]></description>
			<content:encoded><![CDATA[<p>今天在首尔大学读硕士的老同学问了我一个简单的算法，他的要求描述是：</p>
<blockquote><p>多项式参数的穷举：<br />
1*A1+2*A2+3*A3+&#8230;+n*An=n<br />
n是固定值，要打印出所有A的排列。</p></blockquote>
<p>太久没写算法，发现自己在一天的班上下来后，思考能力已经退化到可怕的境界了。最后花了2个多小时才完全写好，通过测试。<br />
简要分析一下（以5为例子）：<span id="more-34"></span></p>
<blockquote><p>5 = 5 * 1<br />
5 = 5 * 0 + 4 * 1 + 1 * 1<br />
5 = 5 * 0 + 4 * 0 + 3 * 1 + 2 * 1<br />
5 = 5 * 0 + 4 * 0 + 3 * 1 + 2 * 0 + 1 * 2<br />
5 = 5 * 0 + 4 * 0 + 3 * 0 + 2 * 2 + 1 * 1<br />
5 = 5 * 0 + 4 * 0 + 3 * 0 + 2 * 1 + 1 * 3<br />
5 = 5 * 0 + 4 * 0 + 3 * 0 + 2 * 0 + 1 * 5</p></blockquote>
<p>其实思路很简单（面向过程版）：</p>
<blockquote><p>1.n为所求的数，建立栈S</p>
<p>2.压入n*1</p>
<p>3.设栈内的队列乘积为X，Y=n-X</p>
<p>4.若Y大于0，压入min(X,Y) * Y/(min(X,Y))；否则进入7</p>
<p>5.若min(X,Y) 等于1，输出一种排列情况，然后：若X不等于n进入4，否则结束。</p>
<p>6.进入4</p>
<p>7.若Y等于0，退栈，压入比刚退栈的系数小1的系数 * 最大倍数</p>
<p>8.进入5</p></blockquote>
<p>下面是写的实际代码（c#，很乱，这里不讲什么美感了）：</p>
<pre class="brush: csharp;">
        static void Main(string[] args)
        {
            Reduce(10);
        }

        static void Reduce(int n)
        {
            Stack&lt;yin&gt; _stack = new Stack&lt;yin&gt;();
            _stack.Push(new yin(n, 1));
            int number = 0;
            int used = n;
            int count = 1;
            int remain = 0;

            Console.WriteLine(&quot;{1}:{0}*1={0}&quot;, n, count);

            while (true)
            {
                if (_stack.Peek().i == 1)
                {
                    yin y1 = _stack.Pop();
                    remain += y1.k;
                    if (y1.k == n)
                    {
                        //结束条件
                        break;
                    }
                }

                remain += _stack.Peek().i;
                yin y = _stack.Pop();
                y.k--;
                _stack.Push(y);

                if (_stack.Peek().k == 0)
                {
                    y = _stack.Pop();
                    number = y.i;
                    if (_stack.Count == 0)
                    {
                        //没有元素了
                        used = y.i - 1;
                    }
                    else
                    {
                        used = number - 1;
                    }

                    int k = remain / used;
                    remain = remain - k * used;

                    _stack.Push(new yin(used, k));

                }

                while (remain &gt; 0)
                {
                    // 小于等于number的最大能被remain除尽的数
                    int p = Math.Min(_stack.Peek().i - 1, remain);

                    if (p == 1)
                    {
                        //输出
                        Console.Write(&quot;{0}:&quot;, ++count);
                        foreach (yin yin in _stack.ToArray())
                        {
                            Console.Write(&quot;{0}+&quot;, yin);
                        }
                        Console.WriteLine(String.Format(&quot;{0}*{1}={2}&quot;, p, remain, n));

                        if (remain / p == n)
                        {
                            //全部结束
                            return;
                        }

                        break;
                    }
                    int k = remain / p;
                    remain -= p * k;
                    _stack.Push(new yin(p, k));
                }
                if (remain == 0)
                {
                    Console.Write(&quot;{0}:&quot;, ++count);
                    int c = 0;
                    foreach (yin yin in _stack.ToArray())
                    {

                        Console.Write(&quot;{0}&quot;, yin);
                        c++;
                        if (c != _stack.Count)
                        {
                            Console.Write(&quot;+&quot;);
                        }
                    }
                    Console.WriteLine(&quot;={0}&quot;, n);
                }

            }
        }

    }

    public struct yin
    {
        public int i, k;
        public yin(int i, int k) { this.i = i; this.k = k; }
        public override string ToString()
        {
            return String.Format(&quot;{0}*{1}&quot;, i,k);
        }
    }
</pre>
 <img src="http://www.imneio.com/wp-content/plugins/feed-statistics.php?view=1&post_id=34" width="1" height="1" style="display: none;" />]]></content:encoded>
			<wfw:commentRss>http://www.imneio.com/2009/10/reduce/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Password Reader for CuteFTP Pro 8【含工具下载】</title>
		<link>http://www.imneio.com/2009/10/cuteftppwd/</link>
		<comments>http://www.imneio.com/2009/10/cuteftppwd/#comments</comments>
		<pubDate>Sun, 11 Oct 2009 07:55:43 +0000</pubDate>
		<dc:creator>neio</dc:creator>
				<category><![CDATA[开发作品]]></category>
		<category><![CDATA[经验之谈]]></category>
		<category><![CDATA[CuteFTP]]></category>
		<category><![CDATA[Password]]></category>
		<category><![CDATA[sm.dat]]></category>
		<category><![CDATA[下载]]></category>
		<category><![CDATA[密码]]></category>
		<category><![CDATA[密码查看]]></category>
		<category><![CDATA[密码读取]]></category>
		<category><![CDATA[查看]]></category>
		<category><![CDATA[破解]]></category>
		<category><![CDATA[解密]]></category>

		<guid isPermaLink="false">http://www.imneio.com/?p=20</guid>
		<description><![CDATA[平时都直接用CuteFTP来管理各个服务器，竟然把密码都忘记掉了。痛定思痛，确定从CuteFTP中把密码挖出来。
CuteFTP Pro中，密码显示都是*号，即使用里面的站点管理器(Site Manager)导出，用的也是星号。用Spy++查看密码框，是空的，也就是说那个框只能用来输入。
那么，要找出密码，可以有三种方法：
一、抓包
用Wireshark(即Ethereal)等工具，可以简单地根据FTP协议分析出来。这个方法以前用过，但似乎对于SSL等连接，这种方法变得不切实际。
二、分析内存
用OllyDbg等工具，调试分析之，然后从内存中找出来。此方法费时费力，每次找都要花一番功夫。
三、读取CuteFTP Pro的文件
我们知道CuteFTP Pro的密码都保存在sm.dat文件中。那么只要分析出sm.dat的结构和密码存储的方法，就可以读出来了。
分析过程不多说，只说结果：
在sm.dat文件中，对于每个站点，都用相同的结构。每个站点前是 0B 00 00 00，接下去是“记录名”，然后是几条类型数据，再下去就是站点，用户名，密码等。（其他不累赘了）密码当然不是用明文，而是加密过的。加密后的密码和原文长度一致，是一一对应的。下面是我分析出其规则后写的解密算法：

uint L = code &#38; 0xF;
L = L &#62; 7 ? L - 8 : L + 8;
uint H = ((code &#38; (byte)0xF0)) - 0x80;
H = H &#62; 0x30 ? H - 0x40 : H + 0x40;
byte PCode = (byte)(L + H);

随手写了个CuteFTP Pro 的密码读取器，用MPL协议发布
CuteFTP Pro Password Reader
上面是编译后的文件下载地址。
注意：运行这个程序需要.NET [...]]]></description>
			<content:encoded><![CDATA[<p>平时都直接用CuteFTP来管理各个服务器，竟然把密码都忘记掉了。痛定思痛，确定从CuteFTP中把密码挖出来。</p>
<p>CuteFTP Pro中，密码显示都是*号，即使用里面的站点管理器(Site Manager)导出，用的也是星号。用Spy++查看密码框，是空的，也就是说那个框只能用来输入。</p>
<p>那么，要找出密码，可以有三种方法：</p>
<p><strong>一、抓包</strong></p>
<p>用Wireshark(即Ethereal)等工具，可以简单地根据FTP协议分析出来。这个方法以前用过，但似乎对于SSL等连接，这种方法变得不切实际。</p>
<p><strong>二、分析内存</strong></p>
<p>用OllyDbg等工具，调试分析之，然后从内存中找出来。此方法费时费力，每次找都要花一番功夫。</p>
<p><strong>三、读取CuteFTP Pro的文件</strong></p>
<p>我们知道CuteFTP Pro的密码都保存在sm.dat文件中。那么只要分析出sm.dat的结构和密码存储的方法，就可以读出来了。</p>
<p>分析过程不多说，只说结果：</p>
<p>在sm.dat文件中，对于每个站点，都用相同的结构。每个站点前是 0B 00 00 00，接下去是“记录名”，然后是几条类型数据，再下去就是站点，用户名，密码等。（其他不累赘了）密码当然不是用明文，而是加密过的。加密后的密码和原文长度一致，是一一对应的。下面是我分析出其规则后写的解密算法：</p>
<pre class="brush: csharp;">
uint L = code &amp; 0xF;
L = L &gt; 7 ? L - 8 : L + 8;
uint H = ((code &amp; (byte)0xF0)) - 0x80;
H = H &gt; 0x30 ? H - 0x40 : H + 0x40;
byte PCode = (byte)(L + H);
</pre>
<p>随手写了个CuteFTP Pro 的密码读取器，用MPL协议发布<br />
<a href="http://www.imneio.com/wp-content/plugins/feed-statistics.php?url=aHR0cDovL3d3dy5pbW5laW8uY29tL3dwLWNvbnRlbnQvdXBsb2Fkcy8yMDA5LzEwL2N1dGVmdHBwd2Quemlw">CuteFTP Pro Password Reader</a><br />
上面是编译后的文件下载地址。</p>
<p>注意：运行这个程序需要<span style="color: #ff0000;">.NET Framework 2.0 或以上版本</span></p>
<p>想对其扩展的朋友，可以联系我拿源码。</p>
 <img src="http://www.imneio.com/wp-content/plugins/feed-statistics.php?view=1&post_id=20" width="1" height="1" style="display: none;" />]]></content:encoded>
			<wfw:commentRss>http://www.imneio.com/2009/10/cuteftppwd/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>
