Exaile-Douban-Covers 0.0.3 Released

一眨眼有大半年没有维护这个插件了,Exaile从0.3.0升级到了0.3.2。严重的是这三个版本的插件接口各不相同,0.3.1新增了cover providers管理, 修改了track获得相应字段的api,简化了CoverSearchMethod的职责(去掉了缓存管理,只负责find_convers和get_conver_data两个功能)。而0.3.2至少也修改了配置管理界面的API,所以可以在0.3.1上工作的版本也不能在0.3.2上工作。

这次升级维护把插件升级到0.0.3,兼容目前Ubuntu仓库里的Exaile 0.3.1.1。0.3.1.1新提供了一个cover provider的配置界面,可以调整cover provider的优先级,如果你听中文歌比较多,建议可以把douban cover放在第一位。

下载页面(doubancovers-0.0.3.exz ):
http://bitbucket.org/sunng/exailedoubancovers/downloads

新版本和0.3.0已经无法兼容,0.3.0的用户可以继续使用0.0.2 。而兼容0.3.2的版本预计要等到10月份之后推出了,用Archlinux和其他自己安装的用户要稍等一阵了。

The post is brought to you by lekhonee v0.7

Posted in: 广告 by Sunng No Comments , ,

Twitter talks about the LBS feature and implementation

这是3月份OReilly Where 2.0会议上Twitter介绍自己LBS功能和实现的幻灯片
http://www.slideshare.net/raffikrikorian/handling-realtime-geostreams-3597425

都封了,越封越傻逼,封封更傻逼。

The post is brought to you by lekhonee v0.7

Posted in: 未分类 by Sunng No Comments

Redis

Redis是一个高性能Key-Value store

Installation

下载解压,make之后就可以直接启动./redis-server 默认读取当前目录下的redis.conf作为配置,亦可参数指定。默认监听6379端口。

Features

支持多种数据结构

相较memcached,redis支持多种数据结构,包括

针对每种数据结构,redis都提供比较完整的操作支持。

高性能

据Wiki上说可以达到110,000 SETs/second, 81,000 GETs/second,数据根据一定的策略存在内存和磁盘上(支持持久化)。从1.1开始支持append-only持久化方式,数据被加到文件中,并进行异步的维护,保证文件的大小。从2.0(即1.3)开始支持virtual memory,当内存占用超过配置文件中vm-max-memory时,数据被写入virtual memory。

Replication

redis支持主从复制,从而提供多台实例进行读操作,可以在slave的配置文件里配置master的地址。

Protocol

redis目前只有基于TCP的文本协议,与memcache类似,有一些改进。
客户端通常发送
命令 参数… 值字节数\r\n
值\r\n

服务端的返回,根据第一个字节,可以判断:

  • - 错误信息
  • + 普通文本信息
  • $ 变长字节数,$6表示CRLF之后有6个字节的字符
  • : 返回一个整数
  • * 返回组数,即*6表示CRLF之后将返回6组变长字符

其他

项目地址
http://code.google.com/p/redis/
http://github.com/antirez/redis/
开发者twitter
http://twitter.com/antirez
http://twitter.com/pnoordhuis

Redis功能简单精悍,很符合Unix哲学,核心redis.c只有一万多行,实在是个让人爱不释手的东西。如果可能,争取把他用到生产环境来取代现在的memcached。

The post is brought to you by lekhonee v0.7

Posted in: 装备 by Sunng No Comments ,

下班了

先汇报一下时间,我这个WP主题默认不显示具体时间,现在是2010年6月22日凌晨4点整,西班牙2:0领先洪都拉斯,比赛进行到75分钟。

我刚刚下班,晚上我们部署了t.sdo.com的新版本,性能有了一定的改善。后半夜发现一台memcached行为诡异,暂且先禁用了那台,踉踉跄跄回家准备睡觉。

今天t.sdo.com正式发布了,现在不需要鸡和马就可以注册登录。产品本身不谈了,如果你不感兴趣说明你不是目标人群,缺乏90后的气质。前两天twitter上有一篇新浪工程师的离职感言,里面透露新浪要做的“游戏平台”,t.sdo.com就是典型的这种东西。至于里面说的新浪那种气氛,,恐怕在国内的互联网公司里,这种现象都比较普遍吧。

邀请链接,大家点这个就可以了
http://isdo.cn/10CM

这就睡觉去,今天不用上班了。

The post is brought to you by lekhonee v0.7

Posted in: 自话 by Sunng 1 Comment ,

近日琐事

最近创作激情很是强烈,又赶上大家在博客上踊跃留言,我继续无聊闲扯吧。

做现在这个项目以来,我总是被需要同时处理多件事情的状况困扰。多任务处理,今天终于发现自己是LIFO的方式,后进先出,总是在做最近发生的事情,之前的就压栈,栈满了没准栈底就自动丢失了(策略就是java.util.concurrent.ThreadPoolExecutor.DiscardOldestPolicy)。用这种方式,耗时较长的任务往往花掉的时间非常长而且不断被打断。

今天公司新鲜事,我们的工牌的带子终于换掉了。这以前带子的颜色表明了森严的等级制度,员工深蓝色,中层红色,高层黄色,访客绿色,外包白色,物业粉色,平时走在公司里花花绿绿的实在是他妈的一道景观。这事还在twitter上被冯大辉retweet了一下搞得地球人都知道了,今天通通换成了统一的红色。对于一个员工来说,今天看见自己领子上挂着一个鲜艳的中层颜色的带子,时常还是有那么一点错觉。

还得说说世界杯,这是我看得第四届世界杯了,已经说不上自己支持哪个队了,为此我都怀疑自己已经是伪球迷了。眼看着当初看球时候的球星现在陆陆续续当了教练,那种沧桑感啊。98年的时候还在收集方便面里的球星卡,那时候法国的5号布兰科,人家今年世界杯以后就要上任了。而像比埃尔霍夫这样96年欧洲杯一战成名的,现在都是德国队领队了。大伙再瞧瞧踢了四届世界杯的球员:

  • 亨利 法国 1998/2002/2006/2010
  • 布冯 意大利 1998/2002/2006/2010
  • 卡纳瓦罗 意大利 1998/2002/2006/2010
  • 李云在 韩国 1998/2002/2006/2010
  • 楢崎正刚 日本 1998/2002/2006/2010
  • 川口能活 日本 1998/2002/2006/2010
  • 里戈贝特-宋 喀麦隆 1994/1998/2002/2010

98年大家都说法国队锋线不行,其实那是是亨利和特雷泽盖的组合,不过这二位确实从2000年欧洲杯才开始成熟。布冯98年的时候还是打酱油吧,卡纳瓦罗那时倒是已经有点名气了。李云在,包括十多年来轮着换的楢崎正刚和川口能活现在都打不上主力了,不过一个个都算是现象。

昨天收到了新买的桌游“全球传染病”(PANDEMIC,名字是恶心了点),这是一个合作性质的游戏,参与的人扮演不同的角色拥有不同的技能为达到相同目标。昨晚自个玩了一局,难度不小,一颗CPU是搞不定了,下回小聚的时候和大伙一起玩吧。话说不知不觉现在我有卡卡松(加四个扩展),三国杀,UNO,矮人金矿和全球传染病,这发展下去要开店了。。。

都是玩的事情了,正经事都没提。最近准备看Practical Clojure,看看Clojure如何Practical吧。

The post is brought to you by lekhonee v0.7

Posted in: 自话 by Sunng No Comments

我在那里吃拉面

“终于找到一家和我身份地位品味收入都相符的拉面馆。” 这条本来要发到twitter上的,结果不料哪哪出了问题,没发出去,却被我吃面条的时候记下来了。自从有了饭否twitter,只言片语多了,真正坐下来搞创作的动力却没有了,咱虽然比不上极少部分搞艺术的男青年,但追求上进也不该含糊是吧。

纵然再有追求,也比不上清真拉面馆热卖鱼香肉丝面。上海郊区天高真主远,远亲不如近邻,再不创个新,小小的拉面馆恐怕连在这里匹配我的身份地位和品味的可能性也没有了。但是在首都的时候就不一样,同样是少数民族兄弟开的面馆,人家可不含糊,别说是买鱼香肉丝了,门都不让进。

宝盛里的半年,我发现最贴近我们民工生活的就要数西北拉面和成都小吃,碗大量足(当然也不会有拿着筷子在碗里一粒一粒拣肉末吃的男士)。就为了第一次在成都小吃发现盖浇饭里鸡丁可以比花生多,我在那家店里活活吃过了夏秋冬,后来我每每想起这事都难免情绪激动。而之所以没能熬到冬去春来,也是因为老板时间长了实在看不下去,问我要不要换点别的。我是受宠若惊,才不得不转战拉面店。那家叫不上名字店,名字不重要你知道它在哪就成,墙上还挂着清真寺的画,就像很多湘菜馆会挂毛主席像一样。你可以想象这样一家店是绝对做不出卖鱼香肉丝的勾当的。十三块一个的烤羊腿是他们冬天的热门;端菜的小孩最多也就初中年纪,解析几何他大概是不会清楚了,但是你不催他他也还是不会给你上菜。

另一家印象深刻的面馆是中关村软件园北门对面的,名字好像叫老马拉面,店的规模还不小,在那个鸟不那啥的地方算是鹤立鸡群了,是软件园民工,西北旺、西二旗一代租住户,应届大学毕业生理想的消费场所。我就在那吃过一次,印象深刻仅仅是因为一位服务员长得好看。那是北门最美好的两件事物之一,另一件是那里成排的杨树,我每次在那里等642路等会被这两件事物陶醉。

思绪万千了又。其实我就是感叹能找到一家10块钱以内打发晚饭晚上十点还不会饿的地方,抑制不住内心的喜悦,又回忆起以前了。

最后标题是借名记唐师曾的书名。

The post is brought to you by lekhonee v0.7

Posted in: 自话 by Sunng 8 Comments ,

Perfomed my first commit to OpenStreetMap.org

每每看到OSM上南京的地图都一阵唏嘘,这么多年了几乎没有任何变化,仅有的一些数据也都是错误百出,身为一个南京人,又是一个GIS专业毕业的,深感压力巨大。

实际上编辑OSM没有大家想象的那么复杂。任何人都可以注册登录网站,用默认的Potlatch工具进行编辑,即使你手上没有数据也可以编辑一些基本的属性,比如把错误的中山路纠正为北京东路。我从MapMyTracks上导出GPX文件上传到OSM,GPS数据会在OSM上被显示出来,根据这些数据稍作加工就是道路信息了。浏览器里的编辑器功能并不强大,KDE桌面的Merkaator的编辑能力要强大得多,可以对道路进行split/join操作,这些操作对之前南京地图上各种错误的数据非常必要。

其实OpenStreetMap可以借助一些背景图进行数字化,但是在国内,目前只有分辨率非常低Yahoo卫星地图可以用。至于Google的卫星地图,由于License的原因,你是不能在编辑自由地图时使用的。

上海的OSM已经非常完善,数据完善的程度、渲染出地图的壮观已经让你难以想象,连去年开通的张江电车已经在地图上标出,还有各个站名。注册后可以发现,仅仅在浦东就有十几位OSM的贡献者。相比之下,南京在这方面一片空白,甚至还没有苏州的地图完善。考虑到南京有这么多学校这么多GIS专业学生,每年做那么多无用的、自以为是的数字化作业,真正有意义的工作却无人问津,并非没有人愿意去做,而恐怕是大部分人对OSM都闻所未闻。

今后每周我回抽出一定的时间来编辑南京的地图,也算是为家乡做一些贡献吧。

The post is brought to you by lekhonee v0.7

Posted in: 自话 by Sunng 2 Comments , , ,

RPC, Serialization and Schema

The post is brought to you by lekhonee v0.7

糖果项目的后端用Java编写,我负责service gateway的开发(暂且叫sergent),服务以Java接口+Annotation的形式声明,与Spring集成使用,Java对象被序列化为JSON和XML(通过jackson和castor)与外部系统交互。专门的JSON Schema和XML Schema是可选的,系统交互通过简明的文档和人工确认。

RPC框架是跨进程、跨系统交互的重要工具,RPC框架中又包括远程调用、网络传输和序列化反序列化等等部分。流行的工具包括Facebook的thrift,Google的Protobuf和原先Hadoop项目下的avro。其中thrift包含远程调用、反序列化、网络等等全部的功能。Protobuf本身是一个序列化反序列化库,另有很多第三方RPC实现,avro目前除了序列化和反序列化的功能,也包含了ipc的HTTP Server和SocketServer等实现。在序列化的格式方面,Thrift支持JSON和二进制协议,Protobuf本身仅有二进制支持,但已经存在第三方的其他格式实现。 avro原生支持二进制和JSON格式。

从效率上来说,二进制方式的序列化要比文本方式的快。Google Code上(最近迁往了github)有一个tpc项目(thrift-protobuf-compare),根据这个项目的最新的比较结果(与原先不同):

protobuf成为了三者中耗时最少的框架,之后是thrift和avro,这次avro的耗时甚至超过了文本方式的jackson(主要在反序列化上)。

但是二进制协议通常都需要定义Schema,thrift / protobuf / avro三者各自定义了Schema的格式,没有类似XSD和Json Schema的统一标准,也就是说,当你需要传输一个对象,就要为它编写一个Schema文件。按照通常的习惯,都是先编写Schema,然后通过命令行工具或者自动构建工具来生成Java source。对于新系统还好说,对旧系统这个改造就比较麻烦了。另外,二进制协议不便于调试,所以各个thrift/protobuf/avro先后也都有JSON的实现,在文本的序列化格式上,JSON对XML的优势是全方位的。

所以综合起来,很难说有一种完美的解决方案。二进制协议的效率高,但是改造、编写Schema的代价并不小,还要面对核心Model被绑架到具体框架的风险。文本协议开发简便,不需要Schema,直接POJO就可以序列化和反序列化,但是在时间和空间上都不如二进制的方式。

补充
从tpc项目的结果上看,kryo在时间、空间上都击败了所有对手,而且,kryo的API非常简洁,不需要Schema文件就可以序列化POJO,听起来太完美了,看来以后sergent要借鉴一下的。

补充 2010-06-14
发现avro现在也有ReflectDatumReader和ReflectDatumWriter,可以通过反射内部自动映射生成Schema,可以尝试一下。

Posted in: 手艺 by Sunng 8 Comments , ,

ibatis infinite loop when getFirstResultSet

前几天上线后老大发现几台负载非常高,dump线程状态后发现多个线程死循环在同一处,于是发现了ibatis的这个bug:

https://issues.apache.org/jira/browse/IBATIS-384

https://issues.apache.org/jira/browse/IBATIS-587

在mysql数据库上,没有结果集时,stmt.getUpdateCount()会返回0,而非-1.
ibatis 2.4.3

  private ResultSet getFirstResultSet(StatementScope scope, Statement stmt) throws SQLException {
    ResultSet rs = null;
    boolean hasMoreResults = true;
    while (hasMoreResults) {
      rs = stmt.getResultSet();
      if (rs != null) {
        break;
      }
      hasMoreResults = moveToNextResultsIfPresent(scope, stmt);
    }
    return rs;
  }

  private boolean moveToNextResultsIfPresent(StatementScope scope, Statement stmt) throws SQLException {
    boolean moreResults;
    // This is the messed up JDBC approach for determining if there are more results
    moreResults = !(((moveToNextResultsSafely(scope, stmt) == false) && (stmt.getUpdateCount() == -1)));
    return moreResults;
  }

  private boolean moveToNextResultsSafely(StatementScope scope, Statement stmt) throws SQLException {
    if (forceMultipleResultSetSupport(scope) || stmt.getConnection().getMetaData().supportsMultipleResultSets()) {
      return stmt.getMoreResults();
    }
    return false;
  }

moreResults恒为真,程序出现死循环。

在mybatis 2.5的代码里,这部分已经修改为:

  private boolean moveToNextResultsIfPresent(StatementScope scope, Statement stmt) throws SQLException {
    boolean moreResults;
    // This is the messed up JDBC approach for determining if there are more results
    boolean movedToNextResultsSafely = moveToNextResultsSafely(scope, stmt);
    int updateCount = stmt.getUpdateCount();

    moreResults = !(!movedToNextResultsSafely && (updateCount == -1));

    //ibatis-384: workaround for mysql not returning -1 for stmt.getUpdateCount()
    if (moreResults == true){
        moreResults = !(!movedToNextResultsSafely && !isMultipleResultSetSupportPresent(scope, stmt));
    }

    return moreResults;
  }

  private boolean moveToNextResultsSafely(StatementScope scope, Statement stmt) throws SQLException {
    if (isMultipleResultSetSupportPresent(scope, stmt)) {
      return stmt.getMoreResults();
    }
    return false;
  }

  /**
   * checks whether multiple result set support is present - either by direct support of the database driver or by forcing it
   */

  private boolean isMultipleResultSetSupportPresent(StatementScope scope,
          Statement stmt) throws SQLException {
      return forceMultipleResultSetSupport(scope) || stmt.getConnection().getMetaData().supportsMultipleResultSets();
  }

这部分条件判断实在很极致了。

新的实现当getUpdateResult是0时,moreResults恒为真,这时再进行一个判断,如果是由于isMultipleResultSetSupportPresent为false导致了moveToNextResultsSafely为false,那么实际moreResults应是false

MyBatis 2.5还有一个issue没有解决,离发布还有一些时间,这个问题只好签出新版本代码自己build了

Posted in: 手艺 by Sunng 4 Comments ,

t.sdo.com上线

昨天搞到3点多,盛大糖果http://t.sdo.com/,昨天晚上终于开放IP给大家访问了。

留一些邀请码给大家

  • 2HlXyYKYz2
  • 2dKoCcQZYV
  • oHBYhO1JPw
  • -~YTMDYmN+
  • IXKYMq0kE@
  • Ub-C@xk8~r

我们后端服务从3月初开始正式开发,11个成员,加了三个多月的班。

Posted in: 广告 by Sunng 2 Comments ,