Tech

Falcon: Django-like urlreverse router

The default Falcon router don't support urlreverse, but fortunately it allows us to use a costomized router.

Override the add_route, adding a aditional params name to specified url template name.

Note: Falcon version should >=0.4 to support this feature.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
from falcon.routing import DefaultRouter


class ReverseRouter(DefaultRouter):
    url_map = {}

    # override add_route to add our map
    def add_route(self, uri_template, method_map, resource, name=None):
        if name:
            self.url_map[name] = uri_template
        DefaultRouter.add_route(self, uri_template, method_map, resource)

    def reverse(self, _name, **kwargs):
        '''
        reverse url
        '''
        assert _name in self.url_map, "url name: %s not in url map" % _name
        url_tmpl = self.url_map.get(_name)
        return url_tmpl.format(**kwargs)

[python] os.system output out-of-order using shell pipe

t.py as below:

1
2
3
4
5
import os

print "### before ps"
os.system("ps")
print "### after ps"

logical is quite simple, if we directly run it: python t.py, output as below, nothing special:

1
2
3
4
5
6
7
### before ps
  PID TTY          TIME CMD
 1619 pts/9    00:00:00 python
 1620 pts/9    00:00:00 sh
 1621 pts/9    00:00:00 ps
18701 pts/9    00:00:00 bash
### after ps

[Android] wrong playback state when playing MIDI as Ringtone

The Problem

  1. play a MIDI file as Ringtone.
  2. check whether .isPlaying() after .play()
1
2
3
4
      Uri midiUri = Uri.parse( "/sdcard/some/path/to/example.midi");
      Ringtone ringtone = RingtoneManager.getRingtone(mContext, midiUri);
      ringtone.play();
      assertTrue("Couldn't play ringtone " + midiUri, ringtone.isPlaying());

The problems is that the last line always fails.

[Java] Catch Thread Exception

Java has a annoying feature that if any Exception happens, you must report it as throws XXXException.

If you want to run something in a Thread, but still want to catch Exception outside that Thread.

1
2
3
4
5
6
7
8
9
10
    ExecutorService executor = Executors.newCachedThreadPool();
    try {
        executor.execute(new Runnable() {
            public void run () {
                // code might throw Throwable or any other Exceptions.
            }
        });
    } catch (Throwable e) {
            // handling exception here.
    }

[Android] Camera callback not be invoked

The Problem

今天用 android.hardware.Camera 写了个简单的拍照函数,代码大致如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
    private void doTakePicture(int cameraId) throws Exception {
        Camera camera = Camera.open(cameraId);
        camera.lock();

        camera.setPreviewDisplay(mActivity.getSurfaceHolder());
        camera.startPreview();

        mMonitor.reset();

        PictureCallback jpegCallback = new PictureCallback() {
            /* callback to save the picture we take */
            @Override
            public void onPictureTaken(byte[] data, Camera camera) {
                try {
                    FileOutputStream fos = new FileOutputStream(mOutFile);
                    fos.write(data);
                    fos.close();
                    Log.i(TAG, "notify take picture done");
                    mMonitor.signal();  // notify done
                } catch (FileNotFoundException e) {
                    Log.e(TAG, "File not found: " + e.getMessage());
                } catch (IOException e) {
                    Log.e(TAG, "IO Exception: " + e.getMessage());
                }
            }
        };

        camera.takePicture(null, null, jpegCallback);

        // wait at most 4s for picture taken done
        boolean success = mMonitor.waitForSignal(4000);
        assertTrue(success);

        camera.stopPreview();
        camera.unlock();
        camera.release();
        camera = null;
    }

[Android] Force route audio stream to wired headset

I want to force route audio stream to headphone for some tests, no matter headset is on or off.

API has been deprecrated

Andoird's AudioManager has such API before, called setRouting , but it has deprecated for quite a long time. Currently, the available APIs can't meet my demands.

public void setRouting (int mode, int routes, int mask)
This method was deprecated in API level 4. Do not set audio routing directly, use setSpeakerphoneOn(), setBluetoothScoOn() methods instead.

[Android] The Story of MediaPlayer.setDataSource [Part.1]

Android MediaPlayer is a big class for all purpose media type playing, including local file and streaming playing.

The story start from MediaPlayer.setDataSource.

android.media package

android.media package locates in frameworks/base/media, and it's Java source is java/android/media.

This package provide various of interface for media playing/recording/decoding etc, including the MediaPlayer we are going to talk about today.

MediaPlayer.setDataSource()

I would not talk much about MediaPlayer constrution, the part we are insterested is what happens after calling setDataSource()

From developer.android, MediaPlayer provide 4 types of method reloading for setDataSource:

1
2
3
4
5
void setDataSource(String path)
void setDataSource(Context context, Uri uri, Map<String, String> headers)
void setDataSource(Context context, Uri uri)
void setDataSource(FileDescriptor fd, long offset, long length)
void setDataSource(FileDescriptor fd)

[Android] Bypass SSL cert check when connecting to localhost through HTTPS

最近需要用HTTPS连接到localhost做一些测试,但是发现一个SSL证书的问题, 用Android的MediaPlayer播放Https内容的时候总是失败在SSL连接握手阶段,应该是localhost证书非法,验证不了,直接导致MediaPlayer拒绝连接。

1
2
javax.net.ssl.SSLProtocolException: SSL handshake terminated: ssl=0xef44d200: Failure in SSL library, usually a protocol error
error:14094416:SSL routines:SSL3_READ_BYTES:sslv3 alert certificate unknown (external/openssl/ssl/s3_pkt.c:1286 0xef40c640:0x00000003)

Level of Security

对于连接的安全级别,可以分为下列3个级别:

  • Level A – no encryption, no verification
  • Level B – encryption, no verification
  • Level C – encryption and verification

Level A 就是相当于http连接,没有任何保护;而Level C就相当于https连接,连接加密且验证连接方。

而对于媒体播放的需求其实更接近于是Level B,只需要传输数据加密,不让别人知道自己看过什么,而对播放源验证不会有那么严格的要求。

[linux] 'No protocol specified' error

今天突然所有的GUI程序都打不开了, 一直提示有

1
2
3
4
oneyoung:/home/oneyoung$google-chrome-stable
No protocol specified

(google-chrome-stable:13264): Gtk-WARNING **: cannot open display: :0

错误无非就两种:

  • No protocol specified
  • cannot open display

奇了怪了, 最近Arch Linux没有升级过, 也没干过神马坏事, 怎么GUI的程序全废了 T.T

A framework for event driven FSM

建立一个通用事件驱动的状态机:

  1. 状态机的架构与具体的事件和状态的定义分开.
  2. 状态与事件是低耦合的, 即状态不用关心是什么事件导致状态机进入这个状态.
  3. 每个状态的进入或者退出, 会触发对应的处理函数.

Implement

以下代码为了结构清晰, 会省略一些细节和保护处理, 也有可能不符合C的强类型语法要求, 就权当成伪代码看待吧, 直接copy & paste, 编译器肯定会报错滴 -,-

利用dropbox自动备份网站数据

我等小blog网站自然是用不上高大上的备份方案, 但是不备份后果很严重, 万一那天VPS公司跑路了, 或者机器挂了, 东西就全没鸟.

穷人只用的起免费的Dropbox =.=

安装

根据自己安装版本选择32或者64位的, 解压后会有一个.dropbox-dist的隐藏目录.

1
2
3
4
5
6
7
# Stable 32-bit:
wget -O dropbox.tar.gz "http://www.dropbox.com/download/?plat=lnx.x86"
 
# Or stable 64-bit:
wget -O dropbox.tar.gz "http://www.dropbox.com/download/?plat=lnx.x86_64"

tar -xvf dropbox.tar.gz

第一次在cmdline运行的时候, 会提示通过一个链接绑定帐号, 照着做就行了.

1
~/.dropbox-dist/dropbox

然后就会在home目录下建立一个Dropbox的目录.

bash: vim 自动补全文件名卡住

本来home目录下的.bashrc用一个git维护着. 今天手贱, 在另一个目录下, 以为存在git, 直接git reset, 然后就悲剧了, home下面有些配置直接被干掉了 T.T

然后就出现各种问题了, 发现bash中输入vim + TAB 之后就卡住了, 只能ctrl + C取消掉, 记得之前搞过, google了一通, 终于把它捞出来了.

好像是bash-completion的问题 (REF: link )

1
2
$ pacman -Ss bash-completion
extra/bash-completion 2.1-2 [installed]

运行一下下面这个就搞定了, 目测gvim, emacs也中枪. 可以加在.bashrc里.

1
complete -f -X '*.@(o|so|so.!(conf)|a|rpm|gif|GIF|jp?(e)g|JP?(E)G|mp3|MP3|mp?(e)g|MPG|avi|AVI|asf|ASF|ogg|OGG|class|CLASS)' vi vim gvim rvim view rview rgvim rgview gview emacs xemacs sxemacs kate kwrite

计算n的阶乘末尾有多少个0

计算n的阶乘末尾有多少个0,例如5! = 120 末尾有1个0,10!= 3628800末尾有2个0。

  • 对于一个多因式相乘, 末尾有多少个0, 取决于有多少个10相乘.
  • 10的倍数也可以为结果贡献0, 比如10, 20, 30, 因此可以记为 P = i * 10
  • 10可以因式分解成5 2, 于是 P = i 5 * 2
  • 对于n!, 共有1 2 ... * n

operator module 加速简单函数

众所周知Python function call的开销比较大, function函数可以获得比较好的封装性, 但是如果只是进行简单的操作, 比如像下面一样, 只把两个数相加, 可能得不偿失.

1
2
def add(x, y):
    return x + y

operator module定义了一组function, 可以对简单的操作符进行封装;它是以C实现的, 直接调用C函数, 省去了function call的开销. 以下只用"+" 操作符作为栗子, 其他的可以查询文档.

与lambda对比测试

1
2
3
4
>>> timeit('add(1, 1)', 'add = lambda x, y: x + y')
0.17214393615722656
>>> timeit('add(1, 1)', 'add = __import__("operator").add')
0.11670303344726562

单个函数看, 有30%的效率提升.

[python] garbage collection 和 weakref

默认情况下, 引用计数(ref count) 已经能cover大部分管理, 被引用时候, 计数加一, 去引用时候, 减一;计数为零时候触发回收操作(对象不一定被销毁, python里有很多对象缓冲池).

Problem 1: 循环引用

引用计数有一个致命的缺点, 当出现循环引用的时候, 就无效了.

为此, python gc collection 为此而生. 监控循环引用.

首先, 定义一个函数触发gc机制(默认是有一个阀值才会触发, 这里我们可以调用gc.collect()手动触发).

new-style class in Python2

Definition of new-style class in python

new-style class Any class which inherits from object. This includes all built-in types like list and dict. Only new-style classes can use Python’s newer, versatile features like __slots__, descriptors, properties, and __getattribute__().

简单来说, new-style class 就是继承与object基类的class. 来看一个例子:

Setup a mail server to send email only

SMTP server

Here I just choose postfix. Someone on the Internet said the configuration was very complicated, but after I install postfix, I found the default config file is OK if you just want to send email from you locathost.

1
sudo apt-get install postfix

At first time when you test sending email, you might encount with such error:

1
2
postdrop: warning: unable to look up public/pickup: 
No such file or directory

That's because old sendmail daemon still running, just stop it and restart postfix can fix:

1
2
3
$ sudo /etc/init.d/sendmail stop 
$ sudo  mkfifo /var/spool/postfix/public/pickup
$ sudo /etc/init.d/postfix restart

Pyhton Naming Conventions

Package & Module

  • 名字尽量短, 全部使用小写
  • Module 在必要时可以使用下划线_, 而package则不建议.
  • 用C或者C++扩展的Module, 在前面加_(比如:_socket)

Class & Exception

  • 统一使用CapWords
  • 只在内部使用的类, 前面加_(比如_CapWords)
  • 对于Exception, 如果确实是错误的话, 加Error后缀

通过kernel Makefile 生成 cscope ctags

在kernel 中使用cscope 经常会出现很多的数据是没有用,比如一个函数被不同版本的驱动定义了很多次,而这些版本是我们不需要的,查找定义是会出现很多的选项,看得眼睛都花了 T.T

于是写了一个脚本,通过kernel makefile 来生成这些数据库,这样查找就能很精确,一步到位 ^_^

Beautiful soup

对象类型

标签 tag

tag这个概念应该对应于XML的元素(Element), 包括起始与结束标签.

1
2
3
4
soup = BeautifulSoup('<b class="boldest">Extremely bold</b>')
tag = soup.b
type(tag)
# <class 'bs4.element.Tag'>

结构如下:

  • tag
    • name
    • attrs
    • string

Python4Android

安装android-scripting

SL4A 下载sl4a_r*.apkPythonForAndroid_r*.apk并依次安装.

远程控制(adb 调试)

运行Server

在手机上打开SL4A app, 然后: 菜单--View--Interpreters--menu--StartServer--Private, 就会建立一个Server "localhost:xxxxx", 其中xxxxx是本地端口号.

adb 端口映射

在本机上运行, 将手机的xxxxx端口映射到本地主机的9999端口. 并导出AP_PORT环境变量, 之后android.py会用到.

1
2
adb forward tcp:9999 tcp:xxxxx
export AP_PORT=9999

部署Django到Lighttpd

Django & FastCGI

软件包依赖

在Django上使用FastCGI需要flup包:

1
pip install flup

运行Django server

Django 内置有runfcgi命令, 建立一个脚本, 运行Django:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#!/bin/sh
app_path='/path/to/django-app/'
p='/var/run/lighttpd/django-fastcgi.pid'
cd "$app_path"
if [ -f $p ]; then
    kill $(cat -- $p)
    rm -f -- $p
fi

exec /usr/bin/env \
    PYTHONPATH="$app_path/.." python \
    manage.py runfcgi \
    method=threaded \
    host=127.0.0.1 \
    port=3033 \
    pidfile="$p"

这里使用的TCP方式, 使用127.0.0.1:3033 地址.

ARCH Linux 安装

准备ISO 文件引导

下载ISO文件

我下的是201108 i686版本

用U盘启动。

因为我用的是multi-boot,不能直接dd,先做一个grub启动菜单

menuentry "Arch Linux i686" {
    search --set -f "/archlinux_i686.iso"
    loopback loop "/archlinux_i686.iso"
    linux (loop)/arch/boot/i686/vmlinuz archisolabel=archiso
    initrd (loop)/arch/boot/i686/archiso.img
}

注意,这里加了 archisolable 选项,会在之后系统安装的时候用到

然后,从U盘启动.系统会提示找不到boot device,这是因为从U盘启动的时候找不到arch iso 安装盘。这时会进入一个shell,可以在这里将ISO 挂载上:

mkdir /u_disk # create a directory for later U-disk mount
mount -t vfat /dev/sdb2 /u_disk #check your U-disk, I install multi-boot in the second partition.
# assigned the ISO to the system
modprobe loop
losetup /dev/loop0 /u_disk/archlinux_i686.iso
ln -s /dev/loop0 /dev/disk/by-label/archiso
exit

从这之后就进入正常的安装过程了 ^_^