搬家到国外

据说中国现在有上百万”裸官”,也就是说在中国但凡是个官,基本上就是”裸”的。家在国外,而身在中国,不辞辛苦的为中国人民做公仆,这是怎样一种国际主义精神?

当年学习政治,听闻外国人民还生活在资本主义的水深火热之中,于是立志长大后要冒着生命危险到国外去解救外国人民于水火之中。长大后才发现,我们的公仆们宁愿自己的家人子女们身先士卒,这是怎么样一种自我牺牲精神?

咱买不起房子,咱在租个服务器在网上搭建了个家。结果不小心就敏感了,被机房拔线了。我们的公仆们为了查封一个网站可以断掉整个机房乃至整个省的网络,不惜代价的为我们的未来营造和谐的网络环境,这是怎么样一种一丝不苟的工作精神?

我个人认为光带三块表,反三俗,不足以营造和谐的网络环境。建议再提出一个倡导三个精神的活动,将公仆们的这种 国际主义精神,自我牺牲精神,一丝不苟的工作精神发扬广大。

我个人在这三个精神的指引下,先将我的博客迁移到国外服务器,自动接受GFW的过滤检验,以免自己博客上的低俗内容毒害了祖国的花朵。

强烈推荐 dreamhost 的主机,功能强大操作简便。一键自动安装wordpress。

推荐wordpress的几个插件:

Auto SyntaxHighlighter 代码高亮插件,基于最新版本的SyntaxHighlighter ( http://alexgorbatchev.com/SyntaxHighlighter/),实现延迟加载功能。缺点是没有提供设置功能,如果要改变SyntaxHighlighter的默认设置(比如代码风格),需要修改下代码。自动换行也有问题,参看:http://xiaoy.info/2010/05/23/120/syntaxhighlighter_white_space/

My Category Order 分类排序插件

Simple Tags 标签管理

Akismet 垃圾评论过滤

感谢 @lanhuai 提供他的虚拟主机给我用。

Google 启用加密搜索独立域名— encrypted.google.com

今天早上突然发现用https://www.google.com搜索内容,会被定向到 https://encrypted.google.com这个域名。

google的官方帮助(http://www.google.com/support/websearch/bin/answer.py?hl=en&answer=173733)上说明:

这样做是为了内容过滤服务更好的工作,它举的是学生的例子,比方学校的老师会过滤学生的搜索内容,而google启用https之后过滤服务失去效果。于是google启用了新的独立域名,学校的过滤服务可以直接把encrypted.google.com这个域名给屏蔽掉。

When students search using https://encrypted.google.com, their searches will bypass any content filters that are in place on your network.
If this is problematic for your school, you can block https://encrypted.google.com.
When students continue to search using http://www.google.com, your content filtering will work as it always has in the past.

 

但我觉得GFW听了这消息也会很高兴。不过暂时这个域名还能用,估计还没反应过来。

设计让生活更美好

    设计让生活更美好–套用下SB会的口号。

 

设计心理学

         虽然有人觉得这本书有点拖沓,但我倒觉得它很平易近人,非专业人士也可以看的津津有味。这本书如果换个别的潮一点的名字,绝对可以成为畅销书。

      当作者批评那种不知道应该推还是拉的门,一排不知道控制哪个灯的开关,还有让人不知道怎么调节的水龙头,简直说到我心坎里去了。一直以为是自己有点笨,看了这个书才知道问题不在我这儿,是设计的人太笨。以前遇到用户抱怨网站或者程序不好用,我就认为是用户太笨,看了这个书才知道问题在我这儿,还是自己太笨。

    
作者提到的三种概念模式,用户模式,设计模式,系统表象。设计模式是设计人员头脑中对系统的概念,用户模式是用户认为的该系统的操作方法。设计人员能理解系统内部原理,所以设计的时候往往从内部原理来设计系统的操作方法。而用户是基于已有的知识和系统表象对产品进行理解。就如作者举的那个空调的例子。这两天北京热的要命,大多数人都会在感觉热的时候把空调的温度调到最低点,想让室温快速降低,然后再把温度调到合适。但其实这种用户模式是错误的,这样并不能加速室温降低,因为空调只有两种状态,工作或者不工作,那个温度阀值只是控制空调在当室内温度到多少度的时候停止工作。设计人员明白这个道理,他设计空调的温度调节其实和定时功能一样,基本上属于一种智能开关,而用户确把它当作加速装置。当然,这个例子里的用户模式并不会影响用户对系统的使用,否则,就说明设计有问题了。

     
看了这本书后,我对日常生活用品的观察方式有了明显变化。日常生活用品的细节上的细微改变,都可以使生活变的更美好一点。不知道诸位是否还记得为了扯开一个塑料袋而像动物一样撕咬的尴尬?是否还记得不小心将匙滑落到热汤里的无奈?一个简单的易拉口和带勾的勺把就解决了这些问题。

    
记得有一次参加豆瓣上一个活动,两个设计界的前辈在那里座谈。其中有位说到了王麻子剪刀。正要听下前辈对这种日常用品的设计有啥高论呢,结果他们又扯到了故宫上。两位似乎对故宫的设计都推崇备至,一位说当年他去故宫参观,到午门那儿就感觉到一种威慑力,这是为什么呢?有什么设计上的玄机么?他用CCAV10走进科学的口气卖了个大关,然后说:皇天后土呀!午门后面的宫殿远看是一个“土”字。我顿时被雷倒,本来打算结束了提个问题:如果我把老家的土院子也改成个“土”字形,是不是别人走到我家门前的时候也会被威慑到?

   
总之,无论故宫的设计有多完美,SB会的建筑设计的有多伟大,CCAV大裤衩设计的有多特别,对普通人的生活来说没多大影响。让生活边的美好的恰恰是这些普通的日常生活用品。

 

 

 

OpenSuse 11.3 的安装问题

帮朋友安装最新的OpenSuse 11.3

结果到最后安装界面的时候提示:

The bootloader is installed on a partition that doesn not lie entirely below 128GB. The system might not boot.

查了一下,原来是要求boot所在分区要在距磁盘MBR(0柱面,0磁道,1扇区)128G以内才行。

解决方法:
1.在C盘切割出100M-200M左右的小分区(前提是你的C盘不能大于128G),挂载到linux的/boot文件夹。

2.让linux分区尽可能靠近C盘(前提还是你的C盘不能大于128G)。我就让他将Windows的D分区删除了给llinux。

3.如果C盘就大于128G,那就只能重新分区了。

估计是grub的寻址范围的问题。没有深究。

WebRebuild-重构人生 北京站年会 总结

今天去参加了一下WebRebuild-重构人生 北京站 年会。

@webrebuild

webrebuild.org第四届年会-北京站[2010.07.17]

来自德国的 Klaus Birkenbihl(http://www.w3.org/People/Klaus/) 老大爷讲的是 Data On The Web(http://www.w3.org/2010/Talks/0717Beijing-KB/),主要介绍了下语义网。他举了个 tripit (http://www.tripit.com/)的例子。这个网站是个帮助你安排旅程的网站,你设定好你的旅程安排后,它会给你推荐合适的机票,酒店等。但这个网站遇到的一个问题就是数据来源。手工维护数据库太麻烦。如果机票,酒店网站提供类似webservice的服务倒也不错,但这种情况很少。再就是用爬虫抓取数据了。面临的问题就是每个网站的网页结构差异很大,数据混杂在html标签中,要抽取有用的数据很麻烦,针对各个网站专门定制规则的话,维护成本有太高,网站页面布局一改变,程序就得重来。老大爷把这种工作与西西弗斯推巨石的工作类比。西西弗斯触怒众神,被惩罚推巨石到山顶。但他每每把巨石快要推到山顶的时候,石头就滚下来了,又得重来。众神认为这是他们能想到的最严厉的惩罚。但程序员何罪之有,要遭受西西弗斯式的惩罚?程序员要从这种工作中解脱就只能期待语义网的普及了。提问的时候,我问了下老大爷,按照他最乐观的估计,语义网被普遍应用大约要多长时间?老大爷说,看这个普遍应用的定义了。但从广泛性上来讲,现在很多大网站都已经尝试了,很多用户其实已经接触了。比方说facebook推出的那个“赞” 的按钮,就是语义网的一种尝试。如果是大多数网站都接受这个概念并应用,那估计还需要个三四年。

PS:感谢老大爷在抽奖的时候抽中了我,得了一件XXL的大T恤。

来自D-Link的蒋定宇(台湾)(@josephj6802)分享了一下如何 建立团队前端开发环境。介绍了许多建立前端开发环境的工具和经验。
他的博客:http://josephj.com/  可惜他的ppt我没能在网络找到。只能等webrebuild官方公布吧。
补充: 定宇的ppt http://www.slideshare.net/josephj/webrebuild (感谢 裕波 提供 2010.7.25 )
他主要分享了几点:
1.用fiddler(http://www.fiddler2.com/fiddler2/)来解决前端开发中各种环境(开发,测试,正式)之间切换带来的问题。后端开发中我们用maven的profile来解决这个问题。但前端中我一直没找到好的方法,一直用比较原始的改host文件的方式。这个软确实不错,但可惜fiddler不支持Linux。
2.对前端的代码用jslint和code sniffer来作语法检查。
3.模块化开发。不过这点后面的张克军的分享更全面,更有实战性。

 

来自Opera的谢子斌(马来西亚)(@zibin) 分享了一下<HTML5,CSS3>

下面是他的幻灯片:
http://www.slideshare.net/zibin/zibin-webrebuild-beijing

博客: http://zibin.tehais.com/
他提到了一个手机页面的debug工具--Dragonfly,可以直接从电脑上连接手机(当然需要手机opera)进行页面的debug。

 

来自腾讯的范俊豪(http://tommyfan.com/blog/)分享了 网页性能优化之路。给大家演示了几个腾讯内部团队制作的用于优化网页性能的小工具。

 

来自豆瓣的张克军(@kejunz) 分享了豆瓣的前端基础架构框架,我觉得这个框架的最主要的功能是实现模块化,从前端到后端。
他的幻灯片在他的博客上公布出来了:http://hikejun.com/blog/?p=585
模块化设计这点上我也是深有感触。当初在公司做CMS的时候也尝试过这个,但最后失败。原因有很多,但主要的有几点:
1.公司内部从上到下要对这个问题达成共识。UI设计,产品策划,前端工程师,后端工程师,都要接受模块化的约束,从策划到设计到开发,都要考虑模块化,带着枷锁跳舞,但还要跳好。老板要眼界长远,开发团队要相对问题,持续推动这个事情。
2.产品要形成稳定的界面风格。这点也很重要,毕竟模块化要牺牲一部分灵活性。张克军举了一个Hello Kitty的例子。所有的Hello Kitty都是由固定的模块组合起来的,但这点丝毫没有影响Hello Kitty的多样性。但你不能要求用Hello Kitty的模块来组合一个大力水手,或者变形金刚。Hello Kitty就是Hello Kitty,它的界面风格很稳定,如果模块需要变化就说明要做的不是Hello Kitty了。网站也一样,这点上豆瓣做的比较好。

 

最后神秘人士彪叔(最初不在日程安排单上)出现,分享他对各种浏览器解析网页的认识。由于时间紧迫,演示有点匆促,有些细节没有看清楚。浏览器对DOM的解析方式不同,导致了页面在不同的浏览器下的不同渲染效果。这也是让众多前端开发人员头痛的事情。只有深入理解了浏览器的内部原理了,才能在解决各种浏览器兼容问题是游刃有余,不会被浏览器的各种小bug卡住。不过他的演示文档我没有找到。

总的来说收获颇多。技术上的这些东西或新意也不多,有些早接触过,有些会后看看幻灯片什么的也都能了解到。但众位嘉宾对技术的精益求精,还有他们的分享精神确实值得佩服,也感染到了我。整体上来说,成长在互联网时代的80后的工程师们已经慢慢的形成了自己的鲜明文化特色。

本人的twitter: @jolestar

如何整理和分享A片?

        我有一堆A片(用堆这个量词似乎不合适,但找不到更合适的能表现数量足够多但又不透露太多细节的量词了),太多了,不好找,我要归类一下。于是我建立了一个树形目录,先按照地域归类,欧美,日韩,华语,其他啥的。然后下面按照主演归类,xxx、xxx、xxxx….啥的。然后发现一个问题,光这样归类还不行,比方还需要个标志,说明是有码的还是无码的。于是我在文件名前面加上了这个标志。后来又发现,还有许多信息需要标明,比方是否有暴力呀,是单人还是多人呀,有剧情还是无剧情呀….似乎还需要个评分功能,标志下好看不好看,以及重要性,最好再能附加上
一段观后感… 于是难住我了。

      语义(Semantic)桌面 就是为类解决这样的需求产生的。这个和语义网(Semantic web)的语义是一个概念。主要原因是现有的文件格式和包含
的语义信息是有限的,比如我上面那个例子。因为文件本身很难附加这些语义信息,即便是可以,众多文件格式,没有个统一的附加标准,计算机很难智能处理。而RDF(资源描述框架,Resource Description
Framework,一种用于描述网络上的信息和资源的的标记语言),是专门用于描述资源的标准。
kde4(linux的一种桌面环境)下的nepomuk项目对这个概念进行了尝试,现在提供了两个简单的功能,一个是打标签的功能,一个是评分评论功能。这样,以后组织文件的时候,就不需要太依赖传统的树形结构,而是用标签这样的更自由的归类方式。同时打分功能让程序能智能的识别出哪些文件对用户来说是重要的文件,在检索或者备份的时候提供更便捷的操作方式。

      下面是 dolphin 的操作截图,右侧面板有打分和标签评论功能。

kde4用strigi对文件信息做全文索引,提供强大的检索功能。不过现在的客户端检索接口做的还不好,只能通过Dolphin的地址栏里输
入:

nepomuksearch:/?query=xxx

这样的查询语句来检索。有个sembrowser的项目,提供可视化的检索配置,不过还处于开发测试阶段,功能也有限。

于是我告诉计算机: 给我 找出播放长度超过30分钟,评分在4星以上,有标签为 多人,暴力,评论里包含 “good” 的片子。计算机就给我一个列表,是不是感觉计算机比以前智能了点?

       好了,归类问题解决了。我看着我的整理结果,踌躇满志。发现“独乐乐不如众乐乐”,于是想分享给好友。咋分享?qq上传?不方便,必须双方都在qq
上,并且目标明确。如果好友说,把你的目录给我看看,我看看对哪个感兴趣再说,咋弄?如果有n个好友想要分享,一个一个传?何况现在qq太不安全了,小心被“JC叔叔”抓去罚款。 于是只能放弃qq。用网上邻居分享?那要不是网上邻居呢? 那在本机启动个ftp或者http服务把文件暴露给外面,让朋友来看?一方面是在局域网里,不好把自己的机器暴露出去,另一方面是暴露出去了怎么
控制,那不就成公开传播了?这个如果让“JC叔叔”逮住了更严重。设置个用户和密码?要是多个好友咋弄?整一套用户系统?要是好友分类别,分级别,关系好的可以看到的
多一点,不好的看到的少一点,咋弄?

于是可以总结一下传统的分享功能的一个重大缺点: 分享的范围很难控制,主要问题在于计算机不知道那个计算机是你的好友的计算机。

       社交(Social)桌面就是为了解决这种需求产生的。利用现有的SNS的关系,整合到桌面上,把电脑桌面扩展成一个协作工作环境。你打开桌面,你就在SNS上了,你就能看见你的好友了列表了,你就可以和你的好友的电脑交互了。同时,也意味着你的电脑也能知道哪些电脑是你的好友了的电脑了。你组织硬盘上的文件的时候,就可以设置一个好友的共享权限。你可以把全部或者部分索引结果暴露给好友,让好友搜索你硬盘上的东西。你还可以共享桌面给好友,让好友看到你在做什么,或者教TA怎么操作电脑。偶尔可以在桌面上和好友一起玩一局SNS游戏。
哈哈,你可以尽可能的发挥想象里构想这个社交化的桌面。

当然,以上说明纯属构想,nepomuk还未实现。同时,安全和隐私问题也是个挑战。

 

总结一下,二者合起来就是 社交化的语义桌面(Social Semantic Desktop) 也就是nepomuk项目的主要两个目标。

这是官方网站:  http://nepomuk.semanticdesktop.org

 

下面是一些相关链接:

http://ossz.blogspot.com/2009/05/nepomuk-strigi-resolving-mystry.html

http://thomasmcguire.wordpress.com/2009/10/03/akonadi-nepomuk-and-strigi-explained/

http://forums.opensuse.org/get-help-here/pre-release-beta/428374-nepomuk-strigi-4-4-a.html

http://www.openrdf.org/

http://www.chimera-bellerofonte.eu/2009/11/nepomuk-meeting-results-and-plans/

http://virtuoso.openlinksw.com/overview/index.htm


为了避免让jc叔叔找上门来检查我的电脑对我罚款,我特此声明:上面的A片的说法纯属虚构。另对冲着我的标题进来并且觉得看了后没什么收获的同学表示歉意。

反模式之流失监听者泄露(Lapsed Listener Leak)

有这样一段代码:

public class LapsedListenerTest {

    public static class A{
        private List<PropertyChangeListener> listeners = new CopyOnWriteArrayList<PropertyChangeListener>();
        private String name;
        public A(String name) {
            this.name = name;
        }
        public void addListener(PropertyChangeListener listener) {
            listeners.add(listener);
        }
        private void fire(String property,Object oldValue,Object newValue) {
            for(PropertyChangeListener listener:listeners) {
                    listener.propertyChange(new PropertyChangeEvent(this, property, oldValue, newValue));
            }
        }
        public void setName(String name) {
            String oldName = this.name;
            this.name = name;
            fire("name", oldName, name);
        }
    }

    public static class B implements PropertyChangeListener{
        private int id;
        private A a;
        //占用内存
        private byte[] bt= new byte[1024*1024];
        public B(A a,int id) {
            this.id = id;
            this.a = a;
            this.a.addListener(this);
        }
        @Override
        public void propertyChange(PropertyChangeEvent evt) {
            System.out.println("on B-"+B.this.id+"("+evt.getPropertyName()+","+evt.getOldValue()+","+evt.getNewValue()+")");
        }
    }

    /**
     * @param args
     * @throws InterruptedException
     */
     public static void main(String[] args) throws InterruptedException {
        A a = new A("A");
        int j = 0;
        while(true) {
            B b = new B(a,j);
            //do some thing with b
            a.setName("A"+j);
            b.dispose();
            j++;
            System.gc();
            Thread.sleep(20);
        }
    }

} 

 

代码片段1

A类的对象生命周期都比较长,而B类的对象生命周期都比较短,它需要监听A类的属性变化而进行一些操作。这个程序运行一下,很快就内存溢出了。

这里明显存在一个反模式:流失监听者泄露(Lapsed Listener Leak)。 由于B类的对象的生命周期比较短,如果在系统运行过程中,大量生成B类的对象,而B的构造函数中有将自己作为监听器加入A的监听器列表中,导致B类的对象无法被垃圾回收器回收。在这里,B自己作为监听器,错误看起来比较明显,但如果用内部匿名类的实现方式:

 

 public B(A a,int id) {
            this.id = id;
            this.a = a;
            this.a.addListener(new PropertyChangeListener() {
                @Override
                public void propertyChange(PropertyChangeEvent evt) {
                    System.out.println("on B-"+B.this.id+"("+evt.getPropertyName()+","+evt.getOldValue()+","+evt.getNewValue()+")");
                }
            });
        }

 

代码片段2

看起来虽然没那么明显,但效果是一样的。因为匿名类的对象会引用自己的父对象。

 

这个反模式在Java用户界面框架(AWT,Swing)使用的过程中出现的比较多,但没出现问题的原因主要有两个:1.桌面软件的运行时间一般不会太长,很少有需要7X24运行的。2.桌面类软件中的组件数目有限,一般也不会导致内存溢出。但如果是服务器端的程序就没这么幸运了。

《Bitter Java》中给出了三种解决方案:

1.显式的删除监听者

在A中增加removeListener接口,当B的生命周期结束后,将其从A的监听器列表里删除。

2.缩短锚的生命周期

确保A类对象的生命周期不要太长,A类的对象如果能尽快被垃圾回收器回收,内存泄露也就不会发生了。

3.弱化引用

用弱引用(WeakReference)关联监听器。弱引用的好处是,如果垃圾回收器检测到一个对象当前只有弱引用,就认为该对象可以被回收了。下面是用弱引用重构后的实例代码:

 

public class LapsedListenerTest2 {

    public static class A{
        private List<WeakReference<PropertyChangeListener>> listeners = new CopyOnWriteArrayList<WeakReference<PropertyChangeListener>>();
        private String name;
        public A(String name) {
            this.name = name;
        }
        public void addListener(PropertyChangeListener listener) {
            listeners.add(new WeakReference<PropertyChangeListener>(listener));
        }
        private void fire(String property,Object oldValue,Object newValue) {
            for(WeakReference<PropertyChangeListener> listenerRef:listeners) {
                PropertyChangeListener listener = listenerRef.get();
                if(listener != null) {
                    listenerRef.get().propertyChange(new PropertyChangeEvent(this, property, oldValue, newValue));
                }else {
                    listeners.remove(listenerRef);
                }
            }
        }
        public void setName(String name) {
            String oldName = this.name;
            this.name = name;
            fire("name", oldName, name);
        }
    }

    public static class B implements PropertyChangeListener{
        private int id;
        private A a;
        private byte[] bt= new byte[1024*1024];

        public B(A a,int id) {
            this.id = id;
            this.a = a;
            this.a.addListener(this);
        }
        @Override
        public void propertyChange(PropertyChangeEvent evt) {
            System.out.println("on B-"+B.this.id+"("+evt.getPropertyName()+","+evt.getOldValue()+","+evt.getNewValue()+")");
        }
        @Override
        protected void finalize() throws Throwable {
            System.out.println("finalize:"+id);
        }
    }

    /**
     * @param args
     * @throws InterruptedException
     */
    public static void main(String[] args) throws InterruptedException {
        A a = new A("A");
        int j = 0;
        B first = null;
        while(true) {
            B b = new B(a,j);
            if(first == null) {
                first = b;
            }
            //do some thing with b
            a.setName("A"+j);
            j++;
            System.gc();
            Thread.sleep(20);
        }
    }
}

 

代码片段3

 运行后可以看出:

由于first引用了第一个B对象,致使该对象一直存活,而其他的B对象都被很快的回收了。是不是一个完美的解决方案?别着急,这儿还有个问题。如果B类采用匿名类监听器的情况呢?(代码片段2的情况)

这样的情况下,所有的监听器都只有弱引用,导致监听器会很快被垃圾回收器回收,即便是B类的对象存活(first)的情况下!所以这种方式要求监听器在A类外部必须还有个引用,并且该引用的生命周期与B一致(B自己或者B的属性)。

综合看来,还是方案1比较可靠,虽然要考手动操作。按照方案1的重构:

 

public class LapsedListenerTest {

    public static class A{
        private List<PropertyChangeListener> listeners = new CopyOnWriteArrayList<PropertyChangeListener>();
        private String name;
        public A(String name) {
            this.name = name;
        }
        public void addListener(PropertyChangeListener listener) {
            listeners.add(listener);
        }
        public void removeListener(PropertyChangeListener listener) {
            listeners.remove(listener);
        }
        private void fire(String property,Object oldValue,Object newValue) {
            for(PropertyChangeListener listener:listeners) {
                    listener.propertyChange(new PropertyChangeEvent(this, property, oldValue, newValue));
            }
        }
        public void setName(String name) {
            String oldName = this.name;
            this.name = name;
            fire("name", oldName, name);
        }
    }

    public static class B implements PropertyChangeListener{
        private int id;
        private A a;
        //占用内存
        private byte[] bt= new byte[1024*1024];
        public B(A a,int id) {
            this.id = id;
            this.a = a;
            this.a.addListener(this);
        }

        @Override
        public void propertyChange(PropertyChangeEvent evt) {
            System.out.println("on B-"+B.this.id+"("+evt.getPropertyName()+","+evt.getOldValue()+","+evt.getNewValue()+")");
        }

        public void dispose() {
            this.a.removeListener(this);
        }

    }

    /**
     * @param args
     * @throws InterruptedException
     */
    public static void main(String[] args) throws InterruptedException {
        A a = new A("A");
        int j = 0;
        while(true) {
            B b = new B(a,j);
            //do some thing with b
            a.setName("A"+j);
            b.dispose();
            j++;
            System.gc();
            Thread.sleep(20);
        }
    }

}

 

 

代码片段4

 

本方案的缺点就是必须显式调用下b.dispose()进行销毁。

不知道还有没有其他的更好的解决方案?

 

linux kde 声音问题

升级了一下kde,然后系统声音就时好时坏,老出现 “phonon 回放设备不工作 “的提示,很是郁闷。

查了下网上,说是要设置下 多媒体的回放设备

但点击 系统设置->多媒体(System Setting->Multimedia),设置窗口立刻崩溃(crash).

显示错误: kcm_phonon.so: undefined symbol: _ZNK6Phonon12GlobalConfig19hideAdvancedDevicesEv

amarok不能播放音乐。

网上查了一下,应该是Phonon的问题

Phonon是什么?Qt从4.4版本开始提供的一套多媒体框架,提供多媒体回放的功能。(phonon的图解说明:http://c-home.appspot.com/2009/03/2/phonon_pic.html

检查了下系统 Phonon  的版本,发现 Phonon的版本与kde不兼容。升级了下phonon,这个问题就不存在了。

如果声音还有问题,根据下面这篇文档设置下ALSA:

http://wiki.archlinux.org/index.php/Advanced_Linux_Sound_Architecture

最后还有一个问题:flash没有声音,无论用什么浏览器。

搜索了一下,是PulseAudio的问题。

PulseAudio is a sound server for POSIX and Win32 systems

参考下面两篇文档的设置:

http://developer.novell.com/wiki/index.php/Feisty/HOWTO:_PulseAudio

http://ubuntuforums.org/showthread.php?t=789578

终于在网上建了个家

记得我刚开始学网页就是一个简单的想法,给自己弄个个人站。

于是开始学习
html,css,photoshop,dreamweaver,javascript,flash。然后又知道用静态html做出来的
网站很难维护,最好是用程序做成动态的。于是又学习asp,php,数据库,java,linux。结果这一下误入歧途,回不来了。法律专业也不搞了,转行写程序了。几年来给别人也做了好些网站程序,但自己最初的那个想法还没实现。本来是想抽空自己写个简单的个人博客用的,但这个想法一直处于构想当中。最
后还是找个现成的单用户blog程序吧。既然喜欢java,那也应该找个java的。找来找去,就找到了这个blog程序—pebble,官方网站
http://pebble.sourceforge.net/ 。咱买不起房子,但在网上给自己搭个家还行吧。

pebble的数据采用xml方式储存,没有用数据库,搭建方便,功能也不错。

对中文支持完全没问题。刚搭建之后,发现查询中文tag的时候会有乱码问题,它的url路径里出现中文了:http://jolestar.com/tags/开源项目/.但后来才发现那是我的mod_jk的配置问题。应该加上

JkOptions +ForwardURICompatUnparsed +ForwardDirectories

这两项。第一项是让apache不要解码,把url提交给tomcat处理。第二项是让apache把目录直接提交给tomcat处理。

这样就没问题了。

好了,开始转我的博客吧。但刚一转就发现,编辑器少个功能:插入代码。pebble默认是用FCKEditor编辑器,弄了一下,发现FCKEditor的插件体系不好,网上找到的FCKEditor的代码插入插件都不太好用,很多是直接把代码格式化成html的格式高亮。这种方式不好,因为这样格式化,用户复制代码的时候会很不方便,会复制上冗余的东西,以后编辑也不方便。好的方式就是用js动态实现高亮,而不是直接用html格式化。看了一下javaeye的代码插入功能,觉得不错。javaeye的编辑器用的是tiny_mce,于是就把博客的编辑器替换成了tiny_mce,又把javaeye的tiny_mce的代码插入插件搬了过来。嘿,还挺好用。在此感谢javaeye。

代码插件有了,然后就是代码高亮。javaeye用的是SyntaxHighlighter, http://alexgorbatchev.com ,但它好像用的是旧版本,或者是它的修改版本,不太好用。于是下载了最新的SyntaxHighlighter,实验了一下,嘿,效果不错。但又发现一个问题。新版本的SyntaxHighlighter把每种语言的高亮js都放在单独文件里,必须提前把需要用到的需要高亮的语言的js都加载进来。但页面模板里没法知道博客的内容会插入那些语言的代码,如果把所有的语言的js都加载进来,会严重影响页面加载速度。于是又写了个动态加载语言js的脚本。

  var syntaxhighlighter_url = "/scripts/syntaxhighlighter/";
  var brushLibs = {js:"JScript",jscript:"JScript",javascript:"JScript",
		  bash:"Bash",shell:"Bash",css:"Css",actionscript3:"AS3",as3:"AS3",cpp:"Cpp",c:"Cpp",
		  csharp:"CSharp",groovy:"Groovy",java:"Java",javafx:"JavaFX",jfx:"JavaFX",
		  perl:"Perl",pl:"Perl",php:"Php",text:"Plain",plain:"Plain",
                 py:"Python",python:"Python",
		  ruby:"Ruby",ror:"Ruby",rails:"Ruby",scala:"Scala",sql:"Sql",xml:"Xml",html:"Xml",
                 xhtml:"Xml",xslt:"Xml"
		  };
  function loadBrushLibs(){
	  var pres = document.getElementsByTagName("pre");
	  for(var i=0;i<pres.length;i++){
		  var pre = pres[i];
		  var className = pre.className;
		  var brush = null;
		  className = className.toLowerCase();
		  if(className.indexOf('brush:')==0){
			  brush = className.substr(className.indexOf(':')+1);
		   }//为了兼容从javaeye转过来的博客的高亮代码
                    else if(pre.getAttribute('name')=='code'){
			   brush = className;
			   pre.className='brush:'+className;
			}
			if(brush==null)
				continue;
			if(eval("brushLibs."+brush)){
		   		loadBrushLib(brush);
			}else{
				pre.className='brush:text';
				loadBrushLib('text');
			}
	   }
   }
function loadBrushLib(brush){
	  var libName = eval("brushLibs."+brush);
	  var id = "brush_"+libName;
	  var scriptTag = document.getElementById(id);
	  if(scriptTag)
		  return;
	  var oHead = document.getElementsByTagName('HEAD').item(0);
	  var oScript= document.createElement("script");
	  oScript.id = id;
	  oScript.type = "text/javascript";
	  oScript.src=syntaxhighlighter_url+"scripts/shBrush"+libName+".js";
	 // oScript.onload=function(){alert("load"+brush)};
	  oHead.appendChild(oScript);
   }

(上面这种方式有问题,因为无法控制js的加载顺序,页面经常会报错。新的方式参看本人的这篇文章:javascript库的延迟加载 )

最后又修改了一下页面模板以及样式,精简了一些js。花了半天时间把以前写的一些在javaeye的博客都转过来了。

我的这个在互联网上的家就搭建起来了。

ps:另外发个牢骚,就简单搞了个个人博客,还非要备案。备案就备案吧,但那个工业和信息化部的备案网站实在太烂了,firefox下干脆用不了。提供个帮助文档,还是word格式的。前一段时间反盗版日,大家都批评盗版软件,但连政府网站都不能起个表率作用,非逼着用户装盗版软件。

第一次烫头发,谷歌搬家了,脑袋烧坏了,西游记还可以这样读等若干流水帐

上周日,在女朋友的逼迫下去理发。结果理发师说我这脑袋,上窄下
宽,咋剪都不好看,要烫一下,让头发蓬起来,就均衡了,于是被忽悠了。由于是第一次烫头发,当那个锅盘一样的东西在脑袋上面转悠并且让脑袋发热的时候,我
就担心这东西会不会把我的脑袋给烧坏了?

周一,下班时分,脑袋有点痛。真的烧坏了?

周二,上班路上就收到短信说谷歌搬家
了!上网一看,门户网站的评论和社区上的言论对比明显,两极分化严重,脑袋有点痛,没想明白咋回事,突然灵光一动,我用屁股想明白了。


人拿出“规则说”批评谷歌:各国的法律不同,规则不同,进入不同的国家就要遵守不同的法律和规则。似乎阮次山大叔批评谷歌的时候就持这一论调。其实遵守规
则这说法我同意,但前提是规则必须是规则。什么是规则?这个概念要定义下估计也能写篇论文,在这里就类推一下,拿交通规则来比较下,我们立刻可以简单的概
括出
规则的两个基本特征:1.规则要有明文公示。没有一个国家会把交通规则藏起来不让大家知道吧?2.规则要有一定的稳定性。没有一个国家会三天两头改交通规
则吧?要是早上弄个绿灯行红灯停,下午就该成红灯行绿灯停,谁受的了?
用着两个基本特征来检验下中国的网络审查规则,有公示么?哪个官方网站公布过滤规则?或者叫敏感词汇?有稳定性么?这个更不用说了。


三,凌晨时分,发烧严重,吃了退烧药。早上起来,不烧了,但脑袋还是痛,请了假去医院。挂号的时候问挂哪个科?我说脑袋痛,于是就到了神经内科。大夫问明
情况后说我应该去发热门诊。我说我不发热了,就是头痛,并且发热不要紧,别让我头疼就行。大夫说头痛是发热引起了,要治头疼就得先治发热。于是开药回来
吃。

周四,发烧到39.5,头痛欲裂。再去医院,这次到发热门诊。还是开药回来吃。

周五,情况好转。


六,看了篇帖子<煮酒探西游 ——
吴闲云全面解读西游记>。算是对西游记的一种另类解读吧。作者用逻辑推理的方式,论证了唐僧其实是那个杀了他爹的强盗的儿子,唐僧后来报仇,其实结
果是弑父。唐僧肉其实早已经被吃过,金蝉子转世十次其实是把自己的肉奉献给众菩萨罗汉吃了。红孩儿是太上老君和铁扇公主的私生子。等等等等。虽然解读的确
实也有点另类,但作者的推理逻辑还是比较严密的,只不过他的大前提条件是西游记这本书的作者写这本书的时候是通过严密的逻辑推理写出来的,许多表面上不符
合逻辑的内容其实是作者有意留下的破绽,让后人来解密。不过我觉得作者这个大前提是有问题的,因为中国自古以来对逻辑这东西不是很感兴趣。战国的时候,还
有几个对逻辑感兴趣的(名家),其实也只能算是诡辩术,搞了几个著名的诡辩悖论题目:”坚白论”,”白马非马论”等等。结果中国的“君子”认为这种用偷换
概念或者混淆法等语言技巧进行的辩论会让人迷惑,无益于”大道”,于是后世基本也没有了传人。其实这种诡辩是逻辑学之母,如古希腊的智者学派也喜欢弄诡
辩。虽然智者学派后来也消亡了,但逻辑学在西方成长起来了。似乎扯远了,我是想说明,在没有逻辑学文化传统的中国文化里要孕育出一本非常有逻辑性的小说似
乎是不可能的,也就是作者的大前提似乎错了。

总结一下,先后关系和因果关系是不同的。这个道理虽然很浅显,但似乎不易懂。中国查
封互联网色情内容的主要一个理由就是色情内容会引导青少年进行性犯罪。经常看到的报道就是抓住了一个强奸犯,然后问他是不是看过色情内容,他回答是,然后
就推理出色情网站的危害。不过我觉得应该问他吃过饭了没,他肯定说吃过了,保暖思淫欲么。那是不是也应该禁饭?